#11568 closed (invalid)
Ordering by related attributes makes distinct() break
| Reported by: | Simon Law | Owned by: | nobody |
|---|---|---|---|
| Component: | Database layer (models, ORM) | Version: | 1.0 |
| Severity: | Keywords: | order_by distinct ForeignKey | |
| Cc: | benoit@…, simon@… | Triage Stage: | Unreviewed |
| Has patch: | no | Needs documentation: | no |
| Needs tests: | no | Patch needs improvement: | no |
| Easy pickings: | no | UI/UX: | no |
Description
The problem is that sorting on an attribute of a related model causes distinct() to fail.
This is because the SELECT DISTINCT operates on the extra column required for the LEFT OUTER JOIN, which makes it impossible to group the desired results.
To reproduce the error, run this test case:
models.py
import django
from django.db import models
class Article(models.Model):
title = models.CharField(max_length=128)
def __unicode__(self):
return self.title
class Comment(models.Model):
article = models.ForeignKey(Article)
comment = models.CharField(max_length=128)
def __unicode__(self):
return "%s on %s" % (self.comment, self.article.title)
tests.py
from django.test import TestCase
from django import db
from django.conf import settings
from .models import Article, Comment
class TestOrderDistinctBug(TestCase):
def test(self):
settings.DEBUG = True
awesome = Article.objects.create(title="Awesome Title")
different = Article.objects.create(title="Different Title")
wonderfull = Article.objects.create(title="Bad Title")
Comment.objects.create(article=awesome, comment="Agreed")
Comment.objects.create(article=awesome, comment="Dummy")
Comment.objects.create(article=different, comment="Yeah")
Comment.objects.create(article=different, comment="Onoz ")
Comment.objects.create(article=wonderfull, comment="First !")
db.reset_queries()
articles = Article.objects.order_by("comment__comment").distinct()
print "articles=%s" % articles
# articles=[<Article: Awesome Title>, <Article: Awesome Title>, <Article: Bad Title>, <Article: Different Title>, <Article: Different Title>]
print "sql is : %s" % db.connection.queries[0]
# sql is : {'time': '0.001',
# 'sql': u'SELECT DISTINCT `order_bug_article`.`id`, `order_bug_article`.`title`, `order_bug_comment`.`comment`
# FROM `order_bug_article` LEFT OUTER JOIN `order_bug_comment` ON (
# `order_bug_article`.`id` = `order_bug_comment`.`article_id`
# ) ORDER BY `order_bug_comment`.`comment` ASC LIMIT 21'}
# count returns the right thing
self.assertEquals(articles.count(), 3)
# but the content of the query set is wrong
self.assertEquals(len(articles), 3)
Change History (2)
comment:1 by , 16 years ago
| Resolution: | → invalid |
|---|---|
| Status: | new → closed |
comment:2 by , 16 years ago
Aw, it's documented, but it's still awful behaviour.
Would you guys take a patch that would fix this up?
Note:
See TracTickets
for help on using tickets.
This is documented: http://docs.djangoproject.com/en/dev/ref/models/querysets/#order-by-fields