I have ran into an issue when using the DjangoConnectionField type in my graphql schema.
I wanted to use my own custom resolver which would filter and sort a queryset from the Django models.
I also wanted to make use of the relay output format.
Inside my Query class used in the Schema, I setup a query field using the DjangoConnectionField.
Then I wrote a custom resolver for it.
My problem now is that the returned queryset from the resolver is ALWAYS returned in the very same order. My custom sorting in the resolver function is completely ignored.
I checked the returned queryset and before it hits the final return, the custom sorting is intact. It only gets destroyed once it gets spit out of the graphql endpoint.
Any ideas how I could keep my custom sort while also enjoying the structure provided by the relay framework (edges, nodes...)?
Is this the intended behaviour of DjangoConnectionField?
P.S.: I explicitly don't want to use django-filter.
In order to provide a bit of reference to the problem, I have attached some code below:
class Query(ObjectType):
projects = DjangoConnectionField(
ProjectType, filter=ProjectFilterInput(), sort=graphene.String())
def resolve_projects(self, info, **args):
filterFields = args.get('filter')
sortFields = args.get('sort')
result = getFilteredProjects(filterFields, sortFields)
pprint(result)
return result
My custom getFilteredProjects function contains the following code:
def getFilteredProjects(filterFields, sortFields):
filteredResult = Project.objects.all()
filters = {
"name": {
"nameContains": "contains"
},
[...]
}
if filterFields:
for field_name, lookups in filters.items():
for lookup_input, lookup_expr in lookups.items():
if filterFields.get(lookup_input):
if lookup_expr == "in":
searchValue = filterFields.get(
lookup_input).split(",")
else:
searchValue = filterFields.get(lookup_input)
filter_args = {field_name + "__" +
lookup_expr: searchValue}
filteredResult = filteredResult.filter(**filter_args)
if sortFields:
sortFieldsArray = sortFields.split(",")
filteredResult = filteredResult.order_by(*sortFieldsArray)
return filteredResult
No matter what I do the "resolve_projects" function always sticks to the same order of records regardless of the chosen filer value, e.g. "-name".
When you print the "result" variable you see that the order is actually influenced. It seems DjangoConnectionField is enforcing its own ordering no matter what you feed it to...
How can I get the same behavior with my own custom sorting?
This here also does not work...
def resolve_projects(self, info, **args):
return Project.objects.order_by("-name")
I have tracked the problem further down. Seems like this is some kind of incompatibility with djangoMPTT. In my particular case I am using an mptt enabled model. Whenever I do so, the returned result set from the model changes order but the output of the resolver reverts back to the tree-enforced order.
If I use order_by with a regular django model all is good.
I am unfortunately not advanced enough yet to do some source digging. Does anybody have any idea what might case this unintended resorting of an mptt-enabled django-model?
I was hoping this might be related to some problem with the Object Type TreeQuerySet but even when querying with the regular django BaseManager to get a QuerySet object graphene still miraculously sorts any resulting query if it comes from an mptt-enabled model...
I am out of ideas.
Ok, if I manually define the model managers in my model definition, I can get it to work:
class OrgUnit(MPTTModel):
name = models.CharField(max_length=150)
code = models.CharField(max_length=50, unique=True)
description = models.TextField(blank=True)
parent = TreeForeignKey(
'self',
on_delete=models.CASCADE,
null=True,
blank=True,
related_name='+')
isActive = models.BooleanField(default=True)
def __str__(self):
return self.name
objects = models.Manager()
tree = TreeManager()
Then in the graphene Query definition:
class Query(ObjectType):
node = relay.Node.Field()
test = DjangoConnectionField(OrgUnitType)
def resolve_test(self, info, **args):
result = OrgUnit.tree.order_by("-name")
print(result)
return result
With this setup for whatever reason I can both use the "objects" and the "tree" manager to get the right order out of the graphql interface of graphene...
Seems like there is something odd going on with the default model manager definition...
This issue has been automatically marked as stale because it has not had recent activity. It will be closed if no further activity occurs. Thank you for your contributions.