#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 django-updates+unsubscr...@googlegroups.com.
To post to this group, send email to django-updates@googlegroups.com.
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.

Reply via email to