Opened 6 years ago

Closed 6 years ago

Last modified 4 years ago

#11306 closed (fixed)

QuerySet.exclude on ManyToMany field raises EmptyResultSet

Reported by: sufian@… Owned by: nobody
Component: Database layer (models, ORM) Version: 1.0
Severity: Keywords: QuerySet, exclude, ManyToMany, EmptyResultSet
Cc: Triage Stage: Unreviewed
Has patch: no Needs documentation: no
Needs tests: no Patch needs improvement: no
Easy pickings: UI/UX:

Description

Given two Models in a database that look like this:

class Foo(models.Model):
    bar_set = models.ManyToManyField('Bar', related_name='foo_set')

class Bar(models.Model):
    pass

If you perform a query such as:

Foo.objects.exclude(bar_set__in=[])

It will not return the expected result with all of the Foo objects that exist, but rather will raise an EmptyResultSet exception.

Example code and stacktrace follows:

>>> Foo.objects.all()
[<Foo: Foo object>, <Foo: Foo object>, <Foo: Foo object>, <Foo: Foo object>, <Foo: Foo object>]
>>> Bar.objects.all()
[<Bar: Bar object>, <Bar: Bar object>, <Bar: Bar object>, <Bar: Bar object>, <Bar: Bar object>]
>>> [ foo.bar_set.all() for foo in Foo.objects.all() ]
[[<Bar: Bar object>], [<Bar: Bar object>], [<Bar: Bar object>], [<Bar: Bar object>], [<Bar: Bar object>]]
>>> Foo.objects.filter(id__in=[])
[]
>>> Foo.objects.exclude(id__in=[])
[<Foo: Foo object>, <Foo: Foo object>, <Foo: Foo object>, <Foo: Foo object>, <Foo: Foo object>]
>>> Foo.objects.filter(bar_set__in=[])
[]
>>> Foo.objects.exclude(bar_set__in=[])
Traceback (most recent call last):
  File "<console>", line 1, in <module>
  File "/Library/Python/2.5/site-packages/django/db/models/manager.py", line 108, in exclude
    return self.get_query_set().exclude(*args, **kwargs)
  File "/Library/Python/2.5/site-packages/django/db/models/query.py", line 496, in exclude
    return self._filter_or_exclude(True, *args, **kwargs)
  File "/Library/Python/2.5/site-packages/django/db/models/query.py", line 505, in _filter_or_exclude
    clone.query.add_q(~Q(*args, **kwargs))
  File "/Library/Python/2.5/site-packages/django/db/models/sql/query.py", line 1254, in add_q
    self.add_q(child, used_aliases)
  File "/Library/Python/2.5/site-packages/django/db/models/sql/query.py", line 1258, in add_q
    can_reuse=used_aliases)
  File "/Library/Python/2.5/site-packages/django/db/models/sql/query.py", line 1136, in add_filter
    can_reuse)
  File "/Library/Python/2.5/site-packages/django/db/models/sql/query.py", line 1491, in split_exclude
    can_reuse=can_reuse)
  File "/Library/Python/2.5/site-packages/django/db/models/sql/query.py", line 1201, in add_filter
    self.where.add((alias, col, field, lookup_type, value), connector)
  File "/Library/Python/2.5/site-packages/django/db/models/sql/where.py", line 48, in add
    params = field.get_db_prep_lookup(lookup_type, value)
  File "/Library/Python/2.5/site-packages/django/db/models/fields/related.py", line 143, in get_db_prep_lookup
    sql, params = value.as_sql()
  File "/Library/Python/2.5/site-packages/django/db/models/sql/query.py", line 267, in as_sql
    where, w_params = self.where.as_sql(qn=self.quote_name_unless_alias)
  File "/Library/Python/2.5/site-packages/django/db/models/sql/where.py", line 91, in as_sql
    sql, params = self.make_atom(child, qn)
  File "/Library/Python/2.5/site-packages/django/db/models/sql/where.py", line 158, in make_atom
    raise EmptyResultSet
EmptyResultSet

Change History (2)

comment:1 Changed 6 years ago by sufian@…

  • milestone changed from 1.2 to 1.1
  • Needs documentation unset
  • Needs tests unset
  • Patch needs improvement unset
  • Resolution set to fixed
  • Status changed from new to closed

Tested in trunk (svn revision 10984), the problem is fixed there.

comment:2 Changed 4 years ago by jacob

  • milestone 1.1 deleted

Milestone 1.1 deleted

Note: See TracTickets for help on using tickets.
Back to Top