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
    }
  }
}
posted @ 2020-09-25 07:12  双葫  阅读(240)  评论(0编辑  收藏  举报