Django Graphene Relay order_by(OrderingFilter)

问题描述 投票:0回答:1

我有一个带有中继器和过滤器的石墨烯接口。它工作得很好,但我想添加order_by选项。我的对象看起来像:

    class FooGQLType(DjangoObjectType):
    class Meta:
        model = Foo
        exclude_fields = ('internal_id',)
        interfaces = (graphene.relay.Node,)
        filter_fields = {
            "id": ["exact"],
            "code": ["exact", "icontains"],
        }
        connection_class = ExtendedConnection

class Query(graphene.ObjectType):
    foo = DjangoFilterConnectionField(FooGQLType)

ExtendedConnection应该不相关,但:

class ExtendedConnection(graphene.Connection):
    class Meta:
        abstract = True

    total_count = graphene.Int()

    def resolve_total_count(root, info, **kwargs):
        return root.length

这使我可以像foo(code_Icontains:"bar")一样进行查询。根据the Graphene documentation,我应该为此在FilterSet中使用OrderingFilter。我觉得有点烦人,因为过滤器应该是自动的,但是如果我这样做的话:

    class FooGQLFilter(FilterSet):
    class Meta:
        model = Foo

    order_by = OrderingFilter(
        fields=(
            ('code', 'code'),
            ('lastName', 'last_name'),
            ('otherNames', 'other_names'),
        )
    )

我收到需要提供fieldsexclude的错误:

AssertionError: Setting 'Meta.model' without either 'Meta.fields' or 'Meta.exclude' has been deprecated since 0.15.0 and is now disallowed. Add an explicit 'Meta.fields' or 'Meta.exclude' to the FooGQLFilter class.

因此,如果我添加一个fields = []使其静音,则它将编译。但是,当我在以下位置使用它时:

foo = DjangoFilterConnectionField(FooGQLType, filterset_class=FooGQLFilter)

我的常规过滤器,例如code_Icontains消失了。我可以在那儿再次添加它们,但这很愚蠢。快速查看源代码,看起来Relay或django-filters已经创建了FilterSet类(很有意义),用这种方法覆盖它显然不是一个好主意。

如何在我的石墨烯中继过滤对象上添加orderBy过滤器?我觉得这应该很简单,但我正在努力解决。

[我也看到了用DjangoFilterConnectionField子类化connection_resolver的示例,该示例以某种方式注入order_by,但告诉我没有orderBy参数。

django graphene-python graphene-django
1个回答
0
投票

我已经修改了a GitHub issue中关于此主题的解决方案:

from graphene_django.filter import DjangoFilterConnectionField
from graphene.utils.str_converters import to_snake_case


class OrderedDjangoFilterConnectionField(DjangoFilterConnectionField):
    """
    Adapted from https://github.com/graphql-python/graphene/issues/251
    Substituting:
    `claims = DjangoFilterConnectionField(ClaimsGraphQLType)`
    with:
    ```
    claims = OrderedDjangoFilterConnectionField(ClaimsGraphQLType,
        orderBy=graphene.List(of_type=graphene.String))
    ```
    """
    @classmethod
    def connection_resolver(cls, resolver, connection, default_manager, max_limit,
                            enforce_first_or_last, filterset_class, filtering_args,
                            root, info, **args):
        filter_kwargs = {k: v for k, v in args.items() if k in filtering_args}
        qs = filterset_class(
            data=filter_kwargs,
            queryset=default_manager.get_queryset(),
            request=info.context
        ).qs
        order = args.get('orderBy', None)
        if order:
            if type(order) is str:
                snake_order = to_snake_case(order)
            else:
                snake_order = [to_snake_case(o) for o in order]
            qs = qs.order_by(*snake_order)
        return super(DjangoFilterConnectionField, cls).connection_resolver(
            resolver,
            connection,
            qs,
            max_limit,
            enforce_first_or_last,
            root,
            info,
            **args
        )

要使用它,只需修改以下查询:

claims = DjangoFilterConnectionField(ClaimsGraphQLType)

claims = OrderedDjangoFilterConnectionField(ClaimsGraphQLType,
        orderBy=graphene.List(of_type=graphene.String))

然后您可以查询:

{ claims(status: 2, orderBy: "-id") { id } }

{ claims(status: 2, orderBy: ["creationDate", "lastName"]) { id } }
© www.soinside.com 2019 - 2024. All rights reserved.