assert test_obj not in TestObj.objects.filter(Q(m2ms__int_value=10) &
Q(m2ms__char_value='bar'))

Why shouldn't test_obj be in that query result? test_obj has a m2m with
int_value 10 and a m2m (although another one) with char_value bar

On Sat, Feb 13, 2016 at 7:45 PM, Lucas Wiman <[email protected]> wrote:

> I'm working on the django-predicate library, which defines in-memory
> evaluation semantics for Q objects. The eventual goal is to precisely
> match the behavior of the ORM on the subset of supported lookup types.
> Yesterday, I noticed a bug in that library, where there was a mismatch with
> the behavior of the ORM.
>
> De Morgan's law is a sort of distributive property for Boolean algebras,
> stating that (A ∧ B) ⇔ ¬(¬A ∨ ¬B). It has an equivalent statement for
> sets and logical predicates. However, it seems Django's Q object does
> *not* obey De Morgan's law, which was somewhat surprising.
>
> I wanted to verify that this intended behavior. If so, does anyone know
> where this is documented or Trac tickets that discuss how & and ~ interact
> when turned into SQL queries?
>
> If it is not intended behavior, I'll file a Trac issue about it and we can
> continue discussion there.
>
> Setup of example models.py
>
> class Base(models.Model):
>     class Meta:
>         abstract = True
>     char_value = models.CharField(max_length=100, default='')
>     int_value = models.IntegerField(default=0)
>     date_value = models.DateField(default=datetime.date.today)
>     datetime_value = models.DateTimeField(default=datetime.datetime.now)
>
>
> class TestObj(Base):
>     m2ms = models.ManyToManyField(
>         'testapp.M2MModel', related_name='test_objs')
>
> class M2MModel(Base):
>     pass
>
> Example
> test_obj = TestObj.objects.create()
> test_obj.m2ms.create(int_value=10, char_value='foo')
> test_obj.m2ms.create(int_value=20, char_value='bar')
>
> assert test_obj not in TestObj.objects.filter(Q(m2ms__int_value=10) &
> Q(m2ms__char_value='bar'))
> assert test_obj in TestObj.objects.filter(~(~Q(m2ms__int_value=10) |
> ~Q(m2ms__char_value='bar')))
>
> If De Morgan's law were obeyed, the two queries would evaluate to the same
> result.  The generated SQL is recorded in my pull request adding a test
> cases reproducing the failure in django-predicate:
> https://github.com/ptone/django-predicate/blob/30d23330e71ecc6a8f01743a43a56b406fe764ee/tests/testapp/tests.py#L215-L242
>
> The key issue here seems to be crossing an m2m relation, which causes the
> negated disjuncts to get evaluated as subqueries.
>
> Relevant Trac Issues
>
> https://code.djangoproject.com/ticket/21956 Same issue, but when the
> fields occur on the same table that's being queried. This issue was
> apparently fixed in Django 1.5.
> https://code.djangoproject.com/ticket/13099
>
> Thanks,
> Lucas
>
> --
> You received this message because you are subscribed to the Google Groups
> "Django users" 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-users.
> To view this discussion on the web visit
> https://groups.google.com/d/msgid/django-users/d2f97578-020d-4b7c-9d03-8e3079a18f2f%40googlegroups.com
> <https://groups.google.com/d/msgid/django-users/d2f97578-020d-4b7c-9d03-8e3079a18f2f%40googlegroups.com?utm_medium=email&utm_source=footer>
> .
> For more options, visit https://groups.google.com/d/optout.
>

-- 
You received this message because you are subscribed to the Google Groups 
"Django users" 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-users.
To view this discussion on the web visit 
https://groups.google.com/d/msgid/django-users/CALn3ei3YirQi-sOEXLh6mFP5d9jkSnR_0hsPbO_1TXOd-4U52w%40mail.gmail.com.
For more options, visit https://groups.google.com/d/optout.

Reply via email to