How to fix AttributeError: 'WhereNode' object has no attribute 'select_format', raised by Django annotate()?
Question:
There are many similar questions on SO, but this specific error message did not turn up in any of my searches:
AttributeError: 'WhereNode' object has no attribute 'select_format'
This was raised when trying to annotate()
a Django queryset with the (boolean) result of a comparison, such as the gt lookup in the following simplified example:
Score.objects.annotate(positive=Q(value__gt=0))
The model looks like this:
class Score(models.Model):
value = models.FloatField()
...
How to fix this?
Answers:
This case can be fixed using the ExpressionWrapper()
Score.objects.annotate(
positive=ExpressionWrapper(Q(value__gt=0), output_field=BooleanField()))
From the docs:
ExpressionWrapper
is necessary when using arithmetic on F()
expressions with different types …
The same apparently holds for Q
objects, although I could not find any explicit reference in the docs.
You can also get this error message if you are trying to filter a count annotation, and accidentally put the filter clause in the wrong place. e.g. if you’re following this example but instead of writing
events = Event.objects.annotate(
paid_participants=Count('participants', filter=Q(participants__is_paid=True))
)
like the example says, you accidentally write
events = Event.objects.annotate(
paid_participants=Count('participants'), filter=Q(participants__is_paid=True)
) # WRONG
then you will get this error message. It’s a silly mistake, but could cost you an hour or two, and ExpressionWrapper
won’t help. (Hopefully this helps somebody else.)
There are many similar questions on SO, but this specific error message did not turn up in any of my searches:
AttributeError: 'WhereNode' object has no attribute 'select_format'
This was raised when trying to annotate()
a Django queryset with the (boolean) result of a comparison, such as the gt lookup in the following simplified example:
Score.objects.annotate(positive=Q(value__gt=0))
The model looks like this:
class Score(models.Model):
value = models.FloatField()
...
How to fix this?
This case can be fixed using the ExpressionWrapper()
Score.objects.annotate(
positive=ExpressionWrapper(Q(value__gt=0), output_field=BooleanField()))
From the docs:
ExpressionWrapper
is necessary when using arithmetic onF()
expressions with different types …
The same apparently holds for Q
objects, although I could not find any explicit reference in the docs.
You can also get this error message if you are trying to filter a count annotation, and accidentally put the filter clause in the wrong place. e.g. if you’re following this example but instead of writing
events = Event.objects.annotate(
paid_participants=Count('participants', filter=Q(participants__is_paid=True))
)
like the example says, you accidentally write
events = Event.objects.annotate(
paid_participants=Count('participants'), filter=Q(participants__is_paid=True)
) # WRONG
then you will get this error message. It’s a silly mistake, but could cost you an hour or two, and ExpressionWrapper
won’t help. (Hopefully this helps somebody else.)