On Monday, August 21, 2017 at 11:28:35 AM UTC+3, Tom Forbes wrote:
>
> > Interestingly enough, just doing a .filter(m2m_relation__foo='bar')
> might change the results
>
> Is that not because it's a filter? Would ".
> annotate(x=F('m2m_relation__foo'))" change the results in any way? Sorry if
> I'm not following.
>
What's happening here is that Django generates an unconstrained join to the
m2m_relation. Unsurprisingly that generates duplicate rows to the queryset.
For example:
class Publisher:
name = CharField()
class Book:
publisher = ForeignKey(Publisher, related_name='books')
print(Publisher.objects.annotate(book_id=F('books__id')).query)
OUT: SELECT publisher.id, book.id as book_id FROM publisher JOIN book ON
book.publisher_id = publisher.id
Now, if there are two books fo any publisher, that publisher will be
outputted twice in the resulting queryset.
Normally you wouldn't want to do this, but even if you do this by accident,
count() and len(qs) should return the same number. And, for .values()
querysets this can be actually useful in some cases.
Note that it's possible to remove the select entry for the annotation, even
if the join can't be removed in this case.
- Anssi
--
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 [email protected].
To post to this group, send email to [email protected].
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/d9f2cded-ef37-4852-8845-1fcc126457ee%40googlegroups.com.
For more options, visit https://groups.google.com/d/optout.