I am working with Django 3.1 ORM and am running (with pytest) a test involving a complex nested query. I get this failure:
self = <django.db.models.expressions.Subquery object at 0x0000027CE184D2B0>
lookup = 'lte'
def get_lookup(self, lookup):
> return self.output_field.get_lookup(lookup)
E TypeError: get_lookup() missing 1 required positional argument: 'lookup_name'
That get_lookup(lookup) to be called is defined (as far as I can see) in django.db.models.query_utils.RegisterLookupMixin as
def get_lookup(self, lookup_name):
...
The corresponding source statement of my test involves something like
value = now() - OuterRef(OuterRef('myattr2')) * timedelta(days=1)
queryset2.annotate(has_x=Exists(queryset.filter(myattr__lte=value)))
and there is more query construction code around it.
My debugger tells me that self.output_field is a DateTimeField object.
So overall:
- The context is an
Existssubquery. - The lookup is
'lte'(as intended). - The call provides a
DateTimeFieldasself(fromoutput_field) and'lte'aslookup_name. - The method-to-be-called expects
selfandlookup_name.
The call should work, shouldn't it?
Where is the TypeError?
The comment by @AlexandrTatarinov is right on; that was my problem as well;
myattris a computed attribute created thusly:But for some reason, Django firmly wants a field instance for the output field, not a field class. So
output_field=DateTimeField()works, but myoutput_field=DateTimeFielddoes not. Add the parentheses and my problem is solved.Ironically, The
output_field=is not even required in this case! Removing it works as well as adding the parens.To reflect on my work process, these were my mistakes:
selfwould be present -- but obviously not carefully enough, mistaking theDateTimeFieldclass for aDateTimeFieldinstance.output_field=DateTimeFieldclause while I debugged a previous problem, but did not take it out again when it did not help. Bad idea.self.output_fieldis aDateTimeFieldobject." and asked myself "Do I know it is aDateTimeFieldobject and not theDateTimeFieldclass?", but I did not go and look in the debugger again, I only recalled that I had checked it and had been satisfied.So my take-home lessons are: