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: | 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)
Change History (2)
by , 16 years ago
comment:1 by , 16 years ago
Resolution: | → invalid |
---|---|
Status: | new → 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).
Example models and test code