10.Filtering过滤
Graphene-Django integrates with django-filter (2.x for Python 3 or 1.x for Python 2) to provide filtering of results. See the usage documentation for details on the format for filter_fields
.
Graphene-Django集成了django-filter(2.x用于python3,1.x用于python2)来提供结果过滤。有关filter_fields
格式的详细信息,请参阅用法文档。
This filtering is automatically available when implementing a relay.Node
. Additionally django-filter
is an optional dependency of Graphene.
当实现relay.Node
时,此筛选将自动可用。此外,django-filter
是Graphene的可选依赖物。
You will need to install it manually, which can be done as follows:
您将需要手动安装它,这可以做如下:
# You'll need to install django-filter
# 你需要安装django-filter
pip install django-filter>=2
After installing django-filter
you’ll need to add the application in the settings.py
file:
在安装了django-filter
之后,你需要在settings.py
文件中添加应用程序:
INSTALLED_APPS = [
# ...
"django_filters",
]
Note: The techniques below are demoed in the cookbook example app.
注意:下面的技术在菜单示例应用程序中演示。
Filterable fields 滤过性的字段
The filter_fields
parameter is used to specify the fields which can be filtered upon. The value specified here is passed directly to django-filter
, so see the filtering documentation for full details on the range of options available.
参数filter_fields
用于指定可筛选的字段。此处指定的值将直接传递给django-filter
,因此请参阅筛选文档了解可用选项范围的完整细节。
For example:
例如:
class AnimalNode(DjangoObjectType):
class Meta:
# Assume you have an Animal model defined with the following fields
# 假设您有一个使用以下字段定义的动物模型
model = Animal
filter_fields = ['name', 'genus', 'is_domesticated']
interfaces = (relay.Node, )
class Query(ObjectType):
animal = relay.Node.Field(AnimalNode)
all_animals = DjangoFilterConnectionField(AnimalNode)
You could then perform a query such as:
然后您可以执行查询,如:
query {
# Note that fields names become camelcased
# 注意字段名称变成驼峰格式
allAnimals(genus: "cat", isDomesticated: true) {
edges {
node {
id,
name
}
}
}
}
You can also make more complex lookup types available:
您还可以使更复杂的查找类型可用:
class AnimalNode(DjangoObjectType):
class Meta:
model = Animal
# Provide more complex lookup types
# 提供更复杂的查找类型
filter_fields = {
'name': ['exact', 'icontains', 'istartswith'],
'genus': ['exact'],
'is_domesticated': ['exact'],
}
interfaces = (relay.Node, )
Which you could query as follows:
您可以查询如下:
query {
# Note that fields names become camelcased
# 注意字段名称变成驼峰格式
allAnimals(name_Icontains: "lion") {
edges {
node {
id,
name
}
}
}
}
Custom Filtersets 自定义Filtersets
By default Graphene provides easy access to the most commonly used features of django-filter
. This is done by transparently creating a django_filters.FilterSet
class for you and passing in the values for filter_fields
.
默认情况下,Graphene 可以方便地获得最常用的django-filter
特性。这是通过透明地为您创建一个django_filters.FilterSet
类并传入filter_fields
的值来实现的。
However, you may find this to be insufficient. In these cases you can create your own FilterSet
. You can pass it directly as follows:
然而,您可能会发现这是不够的。在这些情况下,您可以创建自己的FilterSet
。您可以直接传递它如下:
class AnimalNode(DjangoObjectType):
class Meta:
# Assume you have an Animal model defined with the following fields
# 假设您有一个用以下字段定义的动物模型
model = Animal
filter_fields = ['name', 'genus', 'is_domesticated']
interfaces = (relay.Node, )
class AnimalFilter(django_filters.FilterSet):
# Do case-insensitive lookups on 'name'
# 对'name'执行不区分大小写的查询
name = django_filters.CharFilter(lookup_expr=['iexact'])
class Meta:
model = Animal
fields = ['name', 'genus', 'is_domesticated']
class Query(ObjectType):
animal = relay.Node.Field(AnimalNode)
# We specify our custom AnimalFilter using the filterset_class param
# 我们使用filterset_class参数来指定我们的自定义AnimalFilter
all_animals = DjangoFilterConnectionField(AnimalNode,
filterset_class=AnimalFilter)
You can also specify the FilterSet
class using the filterset_class
parameter when defining your DjangoObjectType
, however, this can’t be used in unison with the filter_fields
parameter:
在定义你的DjangoObjectType
时,你也可以使用filterset_class
参数来指定FilterSet
类,但是,这不能与filter_fields
参数一起使用:
class AnimalFilter(django_filters.FilterSet):
# Do case-insensitive lookups on 'name'
# 对'name'执行不区分大小写的查询
name = django_filters.CharFilter(lookup_expr=['iexact'])
class Meta:
# Assume you have an Animal model defined with the following fields
# 假设您有一个使用以下字段定义的动物模型
model = Animal
fields = ['name', 'genus', 'is_domesticated']
class AnimalNode(DjangoObjectType):
class Meta:
model = Animal
filterset_class = AnimalFilter
interfaces = (relay.Node, )
class Query(ObjectType):
animal = relay.Node.Field(AnimalNode)
all_animals = DjangoFilterConnectionField(AnimalNode)
The context argument is passed on as the request argument in a django_filters.FilterSet
instance. You can use this to customize your filters to be context-dependent. We could modify the AnimalFilter
above to pre-filter animals owned by the authenticated user (set in context.user
).
上下文参数作为django_filters.FilterSet
实例中的请求参数传递。您可以使用它自定义您的过滤器,使其与上下文相关。我们可以修改上面的“AnimalFilter”来预先过滤经过身份验证的用户拥有的动物(设置在context.user
中)。
class AnimalFilter(django_filters.FilterSet):
# Do case-insensitive lookups on 'name'
# 对'name'执行不区分大小写的查询
name = django_filters.CharFilter(lookup_type=['iexact'])
class Meta:
model = Animal
fields = ['name', 'genus', 'is_domesticated']
@property
def qs(self):
# The query context can be found in self.request.
# 可以在self.request中找到查询上下文。
return super(AnimalFilter, self).qs.filter(owner=self.request.user)
Ordering 订购
You can use OrderFilter
to define how you want your returned results to be ordered.
您可以使用“OrderFilter”来定义您希望返回的结果如何被排序。
Extend the tuple of fields if you want to order by more than one field.
如果希望按多个字段排序,则扩展字段的元组。
from django_filters import FilterSet, OrderingFilter
class UserFilter(FilterSet):
class Meta:
model = UserModel
order_by = OrderingFilter(
fields=(
('created_at', 'created_at'),
)
)
class Group(DjangoObjectType):
users = DjangoFilterConnectionField(Ticket, filterset_class=UserFilter)
class Meta:
name = 'Group'
model = GroupModel
interfaces = (relay.Node,)
def resolve_users(self, info, **kwargs):
return UserFilter(kwargs).qs
with this set up, you can now order the users under group:
有了这个设置,你现在可以订购组下的用户:
query {
group(id: "xxx") {
users(orderBy: "-created_at") {
xxx
}
}
}