I would like to sum a field in my resolver of django-graphene using django-filter. Typically my resolvers would look like:
my_model = DjangoFilterConnectionField( MyModelNode, filterset_class=MyModelFilter) def my_resolver(self, args, context, info): return MyModelFilter( data=format_query_args(args), queryset=self).qs
Which works fine.
However, I would like to provide a custom queryset to the model filter so that I can perform aggregations on fields. I'm trying to do something like this:
def my_resolver(self, args, context, info): queryset = MyModel.objects.values( 'customer_id').annotate( cost_amt=Sum('cost_amt', output_field=FloatField())) return MyModelFilter( data=format_query_args(args), queryset=queryset).qs
Inspecting the raw SQL in GraphiQL, it looks correct. However, the error message I receive from GraphQL is
"message": "Received incompatible instance \"{'cost_amt': 260.36, 'customer_id': 300968697}\"."
This is the correct result, but I'm unsure why GraphQL is getting this object from django-graphene. How can I provide a custom queryset and make this work?
3 Answers
Answers 1
I assume that your problem occurs because .values()
returns a dictionary rather than a model instance.
You can try to avoid the usage of .values()
as you can see in the last two examples of the aggregation cheat sheet and in the Generate aggregates for each item in a QuerySet section:
def my_resolver(self, args, context, info): queryset = MyModel.objects.annotate( cost_amt=Sum('cost_amt', output_field=FloatField())) return MyModelFilter( data=format_query_args(args), queryset=queryset).qs
But keep in mind that you will have to adjust your "front-end"/receiver accordingly because now your resolver will return a queryset and not a dictionary.
Answers 2
For queryset to work you need to get instance of the model which you can get using
queryset = MyModel.objects.annotate(cost_amt=Sum('cost_amt', output_field=FloatField()))
and then you can try further actions.
return MyModelFilter(data=format_query_args(args),queryset=queryset).qs
still error
Try ASSET UNION
and see if that works else you can also try DjangoConnectionField
from relay.connection
.
Answers 3
It looks like django-graphene is expecting a QuerySet of model instances, when you call .values()
on a QuerySet you will get back a queryset of dictionaries, hence the Received incompatible instance
.
You may be able to use subquery expressions, or do some rawsql queries both of which will return model instances, it really depends on the type of relationships you have setup on your models.
It almost looks like it may be easier to do this annotation from the other end of the relationship (customer side) as you wouldn't need the to use .values()
but it may not work for what you need.
0 comments:
Post a Comment