Simple enough example – I have a bit of Django code that starts with a queryset…
queryset = MyModel.objects.all()
Later on it performs various filtering, depending on some configurable options…
if something:
queryset = self.queryset.filter(foo=some_foo)
if another_thing:
queryset = self.queryset.filter(bar=some_bar)
And finally it performs the lookup…
try:
obj = queryset.get()
except ObjectDoesNotExist:
raise ValidationError('Does not exist')
Now, because of the flexible way that the filtering needs to occur, it’s possible that the some_foo or some_bar variables might not be of the correct type (eg. we could end up with an empty string attempting to filter against an integer field.) so it’s possible for this code to end up raising a TypeError or a ValueError.
That’s fine, and I can handle the case appropriately, but what’s not clear to me from the ORM contract, is at what point should I expect those exceptions to be raised.
- Will it occur on the
.filter()statement?… - …or on the
.get()statement?… - …or is in underspecified, and I handle it as able to occur on either? (Eg perhaps depending on the implementation of the database backend?)
To answer the original question, a
FieldErrorandValueErrorare raised on the call to filter, when a new queryset is built:I’ll also add that this pattern seems misleading to me, in that
filteris normally used to return a list/iterable of models, rather than one as withget. For clarity and easier handling of the exceptions, I’d suggest this pattern:The other added benefit is that, IIRC, the work of cloning querysets is relatively expensive, so you ignore that overhead, while at the same time making the code cleaner. Going back to your question, with this pattern there’s no question where the exception will be raised.