I have recently become acquainted with some ORM behaviour for reverse 
relationships that "makes no sense", and I'm hoping someone can explain the 
justification for the current behaviour. 

This specifically relates to `filter` behaviour referenced in 29271 
<https://code.djangoproject.com/ticket/29271>, and 16554 
<https://code.djangoproject.com/ticket/16554> which seems tangentially 
related to several issues with `exclude` (24421 
<https://code.djangoproject.com/ticket/24421>, 14645 
<https://code.djangoproject.com/ticket/14645>, 17315 
<https://code.djangoproject.com/ticket/17315>) and aggregate expressions (
16603 <https://code.djangoproject.com/ticket/16603>, 19415 
<https://code.djangoproject.com/ticket/19415>)

Most of the confusion about 'intended' behaviour and confirmed 'bugged' 
behaviour seems to relate to the ORM's use of joins for reverse 
relationships.
I think my personal confusion boils down to two questions.

1) Is there some fundamental limitation in the ORM that prevents reducing 
the number of joins? Several of these tickets indicate how the ORM could 
potentially produce similar results with queries that did not use multiple 
joins. Why is that not desirable behaviour?

2) Why is the current behaviour of `filter` for multi-value relationships 
'intended'? I'm hoping I am missing something obvious but it seems to me 
that `Q` objects would support the type of behaviour suggested in the spanning 
multi-valued relationships 
<https://docs.djangoproject.com/en/dev/topics/db/queries/#spanning-multi-valued-relationships>
 documentation 
in a much more inituative manner. In a test case with models

class Related(models.Model):
    field = models.CharField(max_length=100)

class Main(models.Model):
    field_one = models.CharField(max_length=100)
    field_two = models.CharField(max_length=100)
    related = models.ForeignKey(Related, on_delete=models.CASCADE)


both

>>> Related.objects.filter(Q(main__field_two='2')|Q(main__field_one='1'))

SQL:
SELECT "test_app_related"."id", "test_app_related"."field" FROM 
"test_app_related" INNER JOIN "test_app_main" ON ("test_app_related"."id"= 
"test_app_main"."related_id") WHERE ("test_app_main"."field_two" = "2" OR 
"test_app_main"."field_one" = "1")

and

>>> Related.objects.filter(main__field_two='2').filter(main__field_one='1')

SQL:
SELECT "test_app_related"."id", "test_app_related"."field" FROM "test_app_
related" INNER JOIN "test_app_main" ON ("test_app_related"."id"= "test_app_
main"."related_id") INNER JOIN "test_app_main" T3 ON ("test_app_related".
"id" = T3."related_id") WHERE ("test_app_main"."field_two" = "two" AND T3.
"field_one" = "one")

Produce exactly the same results but the second seems to have an 
unnecessary extra join, and directly contradicts the behaviour of filter 
with non multi-valued fields.



In short, could someone be kind enough to explain the justification for all 
this weird behaviour with multi-value relationships?


Cheers,
  Andrew

-- 
You received this message because you are subscribed to the Google Groups 
"Django developers  (Contributions to Django itself)" 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 https://groups.google.com/group/django-developers.
To view this discussion on the web visit 
https://groups.google.com/d/msgid/django-developers/22234c13-3152-473f-86bd-04b41efd9203%40googlegroups.com.
For more options, visit https://groups.google.com/d/optout.

Reply via email to