Opened 16 years ago

Closed 16 years ago

#7780 closed (invalid)

get returns multiple objects when model includes a ManyToManyField in the default ordering

Reported by: max@… Owned by: nobody
Component: Uncategorized Version: dev
Severity: Keywords:
Cc: Triage Stage: Unreviewed
Has patch: no Needs documentation: no
Needs tests: no Patch needs improvement: no
Easy pickings: no UI/UX: no

Description

Django throws a MultipleObjectsReturned error when getting a single instance of a model that includes a ManyToManyField in the default ordering.

It seems that the related table is joined with an inner join and so the resulting query has extra rows.
I traced the join to the function get_ordering of django\db\models\sql\query.py.

This simple example illustrates the issue best:

from django.db import models

class Topping(models.Model):
    name  = models.CharField(max_length = 50)

    def __unicode__(self):
        return self.name


class Pizza(models.Model):
    name = models.CharField(max_length = 50)
    toppings = models.ManyToManyField(Topping)

    def __unicode__(self):
        return self.name

    class Meta:


# test with the following 
# create some toppings
tomato = Topping(name="Tomato")
tomato.save()
mozzarella = Topping(name="Mozzarella")
mozzarella.save()

# create a pizza
pizza = Pizza(name="Margareta")
pizza.save()

# add the toppings
pizza.toppings.add(tomato)
pizza.toppings.add(mozzarella)

# select the pizza
p = Pizza.objects.get(pk=1)

# You should get the following error:
Traceback (most recent call last):
  File "<console>", line 1, in <module>
  File "c:\python25\lib\site-packages\django\db\models\manager.py", line 82, in get return self.get_query_set().get(*args, **kwargs)
  File "c:\python25\lib\site-packages\django\db\models\query.py", line 285, in get % (self.model._meta.object_name, num, kwargs))
MultipleObjectsReturned: get() returned more than one Pizza -- it returned 2! Lookup parameters were {'pk': 1}

Attachments (1)

models.py (1.2 KB ) - added by max@… 16 years ago.
Example models and test code

Download all attachments as: .zip

Change History (2)

by max@…, 16 years ago

Attachment: models.py added

Example models and test code

comment:1 by Malcolm Tredinnick, 16 years ago

Resolution: invalid
Status: newclosed

"Doctor it hurts when I do this".. "Then don't do that, sir".

As noted in the documentation for ordering, it is legal to include multi-valued fields because there are some situations where it returns sensible results, so prohibiting them always leads to undesired restrictions. That does not mean that including them is a sensible thing to do and you should always never do it.

This isn't a bug in Django because the functionality is needed in some cases. The solution is not to include that field in your default ordering (ordering by multiple valued results hardly ever makes sense).

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