I am using django 1.11:
- I have a model definition that calculates the number of false values on a foreign key attribute, like so:
Model:
class Model(models.Model):
.
.
.
def count_total(self):
return self.anothermodel_set.filter(val=False).count()
View:
class ModelViewSet(viewsets.ReadOnlyModelViewSet):
queryset = Model.objects.all()
serializer_class = ModelSerializerClass
permissions = AuthenticatedReadOnly
pagination_class = StandardResultsSetPagination
def list(self, request):
queryset = self.get_queryset()
# Other annotations...
# Attempt 1: returns wrong count
queryset = queryset.annotate(
a_count=Count(
Case(
When(anothermodel__val=False, then=1),
default=0,
output_field=IntegerField()
)
)
)
# Attempt 2: returns wrong count, same as attempt 1
queryset = queryset.annotate(
b_count=Count(Q(anothermodel__val=False))
)
# Ideally I want to do
queryset = queryset.order_by('count_total')
When I do the ordering by count_total it I'll give
FieldError at /api/endpoint/ Cannot resolve keyword 'count_total' into field.
Because count_total is a model definition.
Serializer:
In my serializer I've modified the to_represantation definition to debug:
def to_representation(self, instance):
return {'id': instance.pk, 'a_count': instance.a_count, 'b_count' : instance.b_count, 'correct_count': instance.count_total()}
Otherwise in my serializer I have:
class Meta:
model = Model
fields = ('id', 'title', 'bunch-of-other-stuff', 'count_total')
The instance.count_total() returns the correct result but I cannot simply use it as queryset.order_by('count_total'). I need to annotate the correct value in order to sort the results and to also avoid n+1 query problems.