#25298: Forbid QuerySet filtering by a related field that expects a single value
when multiple values are returned
-------------------------------------+-------------------------------------
Reporter: timgraham | Owner: Y3K
Type: | Status: assigned
Cleanup/optimization |
Component: Database layer | Version: 1.8
(models, ORM) |
Severity: Normal | Resolution:
Keywords: | Triage Stage: Accepted
Has patch: 0 | Needs documentation: 0
Needs tests: 0 | Patch needs improvement: 0
Easy pickings: 0 | UI/UX: 0
-------------------------------------+-------------------------------------
Comment (by Naddiseo):
To re-add my opinion on this from the other issue: I think the ORM should
be consistent across backends, so it should throw an exception if the
inner queryset could return more than a single row. My reasoning is
basically to prevent vendor lock-in; Django was (is?) marketed as being
mix-and-match for the backends such as database and templating, and Django
would take care of the rest. (But, I'm fairly biased on this since I just
spent a few unpleasant weeks converting raw mysql in our code to use ORM
so that we can eventually switch to postgresql.)
For the use-case that akaariai brought up, perhaps it would have to be
changed to accept a limit of one:
{{{#!python
Foo.objects.filter(related_model__exact=RelatedModel.objects.values('pk')[:1])
# SELECT * FROM Foo WHERE related_model_id = (SELECT pk FROM RelatedModel
LIMIT 1);
}}}
This way it's explicit that you only want 0 or 1 returned from the
subquery. As a side note, does `__exact` allow passing in a model
instance?
{{{#!python
Foo.objects.filter(related_model__exact=RelatedModel.objects.get(pk=1))
}}}
Of course, it's not exactly the same since the `.get` can throw a
`DoesNotExist` exception, and it generates two queries.
An alternate solution is to implicitly add limits, or change `=` to `IN`
if the subquery may return multiple results. However, I am against this
behaviour since - although it may be intuitive - it's implicit and may be
the result of a programmer error that should really be raised as an error
instead of silently accepted.
--
Ticket URL: <https://code.djangoproject.com/ticket/25298#comment:8>
Django <https://code.djangoproject.com/>
The Web framework for perfectionists with deadlines.
--
You received this message because you are subscribed to the Google Groups
"Django updates" group.
To unsubscribe from this group and stop receiving emails from it, send an email
to [email protected].
To post to this group, send email to [email protected].
To view this discussion on the web visit
https://groups.google.com/d/msgid/django-updates/067.dbda77a7fba94aeb5163ddfed7d9d0f1%40djangoproject.com.
For more options, visit https://groups.google.com/d/optout.