ilm*_*rez 7 django-filter graphene-python graphql-python
我正在尝试使用 Django 和 Graphene 执行 GraphQL 查询。要使用 id 查询单个对象,我执行了以下操作:
{
samples(id:"U2FtcGxlU2V0VHlwZToxMjYw") {
edges {
nodes {
name
}
}
}
}
Run Code Online (Sandbox Code Playgroud)
它工作正常。当我尝试使用多个 id 进行查询时出现问题,如下所示:
{
samples(id_In:"U2FtcGxlU2V0VHlwZToxMjYw, U2FtcGxlU2V0VHlwZToxMjYx") {
edges {
nodes {
name
}
}
}
}
Run Code Online (Sandbox Code Playgroud)
在后一种情况下,我收到以下错误:
argument should be a bytes-like object or ASCII string, not 'list'
Run Code Online (Sandbox Code Playgroud)
这是如何定义类型和查询的草图 django-graphene
class SampleType(DjangoObjectType):
class Meta:
model = Sample
filter_fields = {
'id': ['exact', 'in'],
}
interfaces = (graphene.relay.Node,)
class Query(object):
samples = DjangoFilterConnectionField(SampleType)
def resolve_sample_sets(self, info, **kwargs):
return Sample.objects.all()
Run Code Online (Sandbox Code Playgroud)
GlobalIDMultipleChoiceFilter从 django-graphene 有点解决这个问题,如果你在字段名称中输入“in”。您可以创建过滤器,例如
from django_filters import FilterSet
from graphene_django.filter import GlobalIDMultipleChoiceFilter
class BookFilter(FilterSet):
author = GlobalIDMultipleChoiceFilter()
Run Code Online (Sandbox Code Playgroud)
并使用它
{
books(author: ["<GlobalID1>", "<GlobalID2>"]) {
edges {
nodes {
name
}
}
}
}
Run Code Online (Sandbox Code Playgroud)
仍然不完美,但对自定义代码的需求已最小化。
我在实现“in”过滤器时也遇到了麻烦——它现在似乎在 graphene-django 中被错误实现,并且无法按预期工作。以下是使其发挥作用的步骤:
from base64 import b64decode
def get_pk_from_node_id(node_id: str):
"""Gets pk from node_id"""
model_with_pk = b64decode(node_id).decode('utf-8')
model_name, pk = model_with_pk.split(":")
return pk
class SampleType(DjangoObjectType):
class Meta:
model = Sample
filter_fields = {
'id': ['exact'],
}
interfaces = (graphene.relay.Node,)
class Query(object):
samples = DjangoFilterConnectionField(SampleType, id__in=graphene.List(graphene.ID))
def resolve_samples(self, info, **kwargs):
# filter_field for 'in' seems to not work, this hack works
id__in = kwargs.get('id__in')
if id__in:
node_ids = kwargs.pop('id__in')
pk_list = [get_pk_from_node_id(node_id) for node_id in node_ids]
return Sample._default_manager.filter(id__in=pk_list)
return Sample._default_manager.all()
Run Code Online (Sandbox Code Playgroud)
这将允许您使用以下 api 调用过滤器。请注意签名中实际数组的使用(我认为这是一个比发送逗号分隔的值字符串更好的 API)。该解决方案仍然允许您向请求添加其他过滤器,并且它们将正确链接在一起。
{
samples(id_In: ["U2FtcGxlU2V0VHlwZToxMjYw", "U2FtcGxlU2V0VHlwZToxMjYx"]) {
edges {
nodes {
name
}
}
}
}
Run Code Online (Sandbox Code Playgroud)
| 归档时间: |
|
| 查看次数: |
3825 次 |
| 最近记录: |