Here's the ticket:

https://code.djangoproject.com/ticket/6785

tl;dr: Calling .get() on a badly filtered queryset can result in lots
of database rows being fetched and wrapped in Python objects for no
gain.

Currently .get() logic is as follows: clone the queryset, prepopulate
its full cache, check if more than one row was returned and if so,
raise MultipleObjectsReturned.

This works fine if the query returns two or five rows. It's not so
fine if the query results in thousands or millions of rows being
returned. While working on a large online store we had one of the
production servers die while trying to fetch twenty something million
rows because of a programming error that resulted in wrong Q object
being used as a filter.

The only reason all rows are fetched is to return an accurate counter
as part of the exception message. This counter is not accessible
programmatically and having the exact number there is of little value.
The ticket proposes to add a safeguard by limiting the database to at
most two results. The logic then is simple: if zero rows are returned,
raise ObjectDoesNotExist, if two, raise MultipleObjectsReturned. The
latter could possibly execute a second COUNT query if DEBUG is enabled
and the counter is deemed important enough to keep.

Of course you can work around the whole problem by not writing buggy
code but we all know how it works. In the mentioned case even unit
tests did not help as there were not enough records in the database to
trigger MultipleObjectsReturned.

Related pull request: https://github.com/django/django/pull/1139

-- 
Patryk Zawadzki
I solve problems.

-- 
You received this message because you are subscribed to the Google Groups 
"Django developers" group.
To unsubscribe from this group and stop receiving emails from it, send an email 
to django-developers+unsubscr...@googlegroups.com.
To post to this group, send email to django-developers@googlegroups.com.
Visit this group at http://groups.google.com/group/django-developers?hl=en.
For more options, visit https://groups.google.com/groups/opt_out.


Reply via email to