Hey guys,
We've noticed that in the last updates, the attribute 'order_by' got removed from the models and requests.
Is there something in the works for replacing it?
Can you suggest an alternative for us to use?
Why was this option removed?
Thank you guys in advance. Best regards.
Reference links:
I am only a graphene-django user not a contributor...
To my understanding, the problem originated from breaking change in django_filter API when it was updated from 0.15.X to 1.0.X
So to whoever using django_filter, order_by and order_by_fields have to be rewritten using OrderingFilter, and that is what precisely was done by @syrusakbary in 8dfe7bbcf5765d767d7db68ebb9a22c940cea9b6 as you have mentioned.
As someone who has been using graphene for quite some time, you would know when you cannot find something in the docs, you would be able to find the "docs" in tests. So first I looked to https://github.com/graphql-python/graphene-django/commit/8dfe7bbcf5765d767d7db68ebb9a22c940cea9b6#diff-c2306cf71ff66425b581488ef4ac5191 to learn how to write django_filters.FilterSet with OrderingFilter in the correct fashion.
Say you have a UserModel with created_at field where you want to apply 'order_by' to, then you would be writing the FilterSet like:
from django_filters import FilterSet, OrderingFilter
class UserFilter(FilterSet):
class Meta:
model = UserModel
order_by = OrderingFilter(
fields=(
('created_at', 'created_at'),
)
)
Then assume you have a GroupModel which has a users field that point to a bunch of UserModel. By looking at the test cases, the problem can be resolved by writing custom filterset_class in your connection, so Group in your schema.py should be written as:
class Group(DjangoObjectType):
users = DjangoFilterConnectionField(Ticket, filterset_class=UserFilter)
class Meta:
name = 'Group'
model = GroupModel
interfaces = (relay.Node,)
Ideally, at this step, the problem should be solved already. But when you look closely, you would find out despite now you can make queries like:
{
group(id: "xxx") {
users(orderBy: "-created_at") {
xxx
}
}
}
The returned users does not reflect the order you asked for. By step tracing the execution, you will find out somehow during https://github.com/graphql-python/graphene-django/blob/master/graphene_django/filter/fields.py#L23-L29, the filterset_class passed in is not UserFilter but the default filter generated by graphene, which does not support OrderingFilter. So we will need to write the resolver for Group schema manually, like:
class Group(DjangoObjectType):
users = DjangoFilterConnectionField(Ticket, filterset_class=UserFilter)
class Meta:
name = 'Group'
model = GroupModel
interfaces = (relay.Node,)
def resolve_users(self, args, context, info):
return UserFilter(data=args, queryset=self.users).qs
And I think you are good to go.
(Sorry I myself is using Relay at client thus using relay.Node etc. I am sure you will figure out how to do it using normal Node)
I do hope in the future there will be a more elegant way to bind a custom FilterSet to a Node. This solution is only temporary and I do not feel this way of writing OrderingFilter is the right way to go. But I myself is not able to make a PR for that. Hope someone can help with that :)
@blakegong your answer is very helpful. thanks a lot!
@syrusakbary Do you want help addressing this issue. I can attempt to write a PR for this behavior.
@blakegong Thanks! very much!
@blakegong thanks, helped me a lot!
(To all copy-paste people like me: There is a typo in the Userfilter filelds ;) )
@blakegong Hi Blake, appreciate your post. How would you write the arguments now in
def resolve_users(self, args, context, info):
return UserFilter(data=args, queryset=self.users).qs
Now that graphene has updated it's argument structure to def resolve_users(self, info **kwargs)
?
@jeffreybrowning are you still available to help with this refinement?
You can use the following code:
def resolve_users(self, info, **kwargs):
# make sure you remove from **kwargs any field your Filter doesn't expect
return UserFilter(kwargs).qs.order_by('whatever-field-you-want-to-sort')
@pedromtorres good spot, you can do this. I think I will tag this for documentation improvement based on @blakegong 's excellent response and his quote:
As someone who has been using graphene for quite some time, you would know when you cannot find something in the docs, you would be able to find the "docs" in tests.
Most helpful comment
I am only a graphene-django user not a contributor...
To my understanding, the problem originated from breaking change in django_filter API when it was updated from 0.15.X to 1.0.X
So to whoever using django_filter, order_by and order_by_fields have to be rewritten using OrderingFilter, and that is what precisely was done by @syrusakbary in 8dfe7bbcf5765d767d7db68ebb9a22c940cea9b6 as you have mentioned.
As someone who has been using graphene for quite some time, you would know when you cannot find something in the docs, you would be able to find the "docs" in tests. So first I looked to https://github.com/graphql-python/graphene-django/commit/8dfe7bbcf5765d767d7db68ebb9a22c940cea9b6#diff-c2306cf71ff66425b581488ef4ac5191 to learn how to write django_filters.FilterSet with OrderingFilter in the correct fashion.
Say you have a
UserModelwithcreated_atfield where you want to apply 'order_by' to, then you would be writing the FilterSet like:Then assume you have a
GroupModelwhich has ausersfield that point to a bunch ofUserModel. By looking at the test cases, the problem can be resolved by writing customfilterset_classin your connection, so Group in yourschema.pyshould be written as:Ideally, at this step, the problem should be solved already. But when you look closely, you would find out despite now you can make queries like:
The returned
usersdoes not reflect the order you asked for. By step tracing the execution, you will find out somehow during https://github.com/graphql-python/graphene-django/blob/master/graphene_django/filter/fields.py#L23-L29, thefilterset_classpassed in is notUserFilterbut the default filter generated by graphene, which does not support OrderingFilter. So we will need to write the resolver forGroupschema manually, like:And I think you are good to go.
(Sorry I myself is using Relay at client thus using relay.Node etc. I am sure you will figure out how to do it using normal Node)
I do hope in the future there will be a more elegant way to bind a custom
FilterSetto aNode. This solution is only temporary and I do not feel this way of writing OrderingFilter is the right way to go. But I myself is not able to make a PR for that. Hope someone can help with that :)