Opened 16 years ago

Closed 16 years ago

#7095 closed (fixed)

Error with Many2Many filter() in models managers after queryset-refactor merge

Reported by: fcaprioli@… Owned by: nobody
Component: Database layer (models, ORM) Version: dev
Severity: Keywords:
Cc: Triage Stage: Accepted
Has patch: no Needs documentation: no
Needs tests: no Patch needs improvement: no
Easy pickings: no UI/UX: no

Description

Hi,
first of all, thank you all for your excellent work; after the qs-rf branch merge, there is a small regression that cause a python error in where.py during an update() if a custom Manager tries to .filter() thru a ManyToManyField in get_query_set().
This breaks, for example, CurrentSiteManager with a M2M 'site' field.

So, if you have a model like:

from django.db import models
from django.contrib.sites.models import Site
from django.contrib.sites.managers import CurrentSiteManager

class Dummy(models.Model):
    dumb = models.TextField()
    site = models.ManyToManyField(Site)
    
    objects = CurrentSiteManager()

def dummy_view(request):
    t = Dummy.objects.create(dumb='abc')
    t.site.add(settings.SITE_ID)
    t.save()

t.save() would give a TypeError: object of type 'Query' has no len().
At some point, a Query object get passed to make_atom rather than a list.
This is the traceback:

Traceback:
File "D:\Arturo\django\core\handlers\base.py" in get_response
  82.                 response = callback(request, *callback_args, **callback_kwargs)
File "D:\Arturo\arturo5\magazine\views_manager_article.py" in article_add
  45.     t.save()
File "D:\Arturo\django\db\models\base.py" in save
  298.         self.save_base()
File "D:\Arturo\django\db\models\base.py" in save_base
  338.                     manager.filter(pk=pk_val)._update(values)
File "D:\Arturo\django\db\models\query.py" in _update
  299.         query.execute_sql(None)
File "D:\Arturo\django\db\models\sql\subqueries.py" in execute_sql
  112.         super(UpdateQuery, self).execute_sql(result_type)
File "D:\Arturo\django\db\models\sql\query.py" in execute_sql
  1432.             sql, params = self.as_sql()
File "D:\Arturo\django\db\models\sql\subqueries.py" in as_sql
  136.         where, params = self.where.as_sql()
File "D:\Arturo\django\db\models\sql\where.py" in as_sql
  61.                     sql, params = self.make_atom(child, qn)
File "D:\Arturo\django\db\models\sql\where.py" in make_atom
  130.             return ('%s IN (%s)' % (field_sql, ', '.join(['%s'] * len(value))),

Exception Type: TypeError at /arturo/magazine/add/
Exception Value: object of type 'Query' has no len()

Change History (4)

comment:1 by Malcolm Tredinnick, 16 years ago

(In [7494]) Allow Query objects to be values in query filters. This already existed for
relations, but not for normal fields. The latter comes up naturally in some
update statements.

Refs #7095

comment:2 by Malcolm Tredinnick, 16 years ago

Triage Stage: UnreviewedAccepted

The above commit fixes the problem for SQLite and PostgreSQL. Unfortunately, it reveals another bug that affects MySQL users because of MySQL's non-standard UPDATE syntax rules. Working on that piece of the puzzle now.

comment:3 by Malcolm Tredinnick, 16 years ago

(In [7495]) Added a test to demonstrate the remaining problem in #7095.

Only fails for MySQL (because they've made some interesting syntax choices).
Refs #7095.

comment:4 by Malcolm Tredinnick, 16 years ago

Resolution: fixed
Status: newclosed

(In [7496]) Made some types of nested update queries very slightly more efficient at the
database level. Also worked around the fact that MySQL (and maybe other
backends we don't know about) cannot select from the table they're updating.

Fixed #7095.

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