Opened 7 years ago

Closed 7 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: master
Severity: Keywords:
Cc: Triage Stage: Unreviewed
Has patch: no Needs documentation: no
Needs tests: no Patch needs improvement: no
Easy pickings: UI/UX:


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\

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):

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

    def __unicode__(self):

    class Meta:

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

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

# add the toppings

# 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\", line 82, in get return self.get_query_set().get(*args, **kwargs)
  File "c:\python25\lib\site-packages\django\db\models\", 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) (1.2 KB) - added by max@… 7 years ago.
Example models and test code

Download all attachments as: .zip

Change History (2)

Changed 7 years ago by max@…

Example models and test code

comment:1 Changed 7 years ago by mtredinnick

  • Needs documentation unset
  • Needs tests unset
  • Patch needs improvement unset
  • Resolution set to invalid
  • Status changed from new to closed

"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