diff options
| author | Malcolm Tredinnick <malcolm.tredinnick@gmail.com> | 2007-10-14 22:38:54 +0000 |
|---|---|---|
| committer | Malcolm Tredinnick <malcolm.tredinnick@gmail.com> | 2007-10-14 22:38:54 +0000 |
| commit | a1d160e2ea22cb010b276cfc2a085f9cd3d81b22 (patch) | |
| tree | 320835f387fc4f649545b3286dd8343d4c2bd6d8 /tests | |
| parent | 6678de130c9539d2103b5c72561c0869f0d838d7 (diff) | |
queryset-refactor: Fixed a large bag of order_by() problems.
This also picked up a small bug in some twisted select_related() handling.
Introduces a new syntax for cross-model ordering: foo__bar__baz, using field
names, instead of a strange combination of table names and field names. This
might turn out to be backwards compatible (although the old syntax leads to
bugs and is not to be recommended).
Still to come: fixes for extra() handling, since the new syntax can't handle
that and doc updates.
Things are starting to get a bit slow here, so we might eventually have to
remove ordering by many-many and other multiple-result fields, since they don't
make a lot of sense in any case. For now, it's legal.
Refs #2076, #2874, #3002 (although the admin bit doesn't work yet).
git-svn-id: http://code.djangoproject.com/svn/django/branches/queryset-refactor@6510 bcc190cf-cafb-0310-a4f2-bffc1f526a37
Diffstat (limited to 'tests')
| -rw-r--r-- | tests/modeltests/reserved_names/models.py | 2 | ||||
| -rw-r--r-- | tests/regressiontests/queries/models.py | 126 |
2 files changed, 116 insertions, 12 deletions
diff --git a/tests/modeltests/reserved_names/models.py b/tests/modeltests/reserved_names/models.py index a11b8d9f88..f698b5bc49 100644 --- a/tests/modeltests/reserved_names/models.py +++ b/tests/modeltests/reserved_names/models.py @@ -45,8 +45,6 @@ h b >>> print v.where 2005-01-01 ->>> Thing.objects.order_by('select.when') -[<Thing: a>, <Thing: h>] >>> Thing.objects.dates('where', 'year') [datetime.datetime(2005, 1, 1, 0, 0), datetime.datetime(2006, 1, 1, 0, 0)] diff --git a/tests/regressiontests/queries/models.py b/tests/regressiontests/queries/models.py index 64baacc32d..c775772ada 100644 --- a/tests/regressiontests/queries/models.py +++ b/tests/regressiontests/queries/models.py @@ -1,5 +1,5 @@ """ -Various combination queries that have been problematic in the past. +Various complex queries that have been problematic in the past. """ from django.db import models @@ -12,9 +12,29 @@ class Tag(models.Model): def __unicode__(self): return self.name +class Note(models.Model): + note = models.CharField(maxlength=100) + + class Meta: + ordering = ['note'] + + def __unicode__(self): + return self.note + +class ExtraInfo(models.Model): + info = models.CharField(maxlength=100) + note = models.ForeignKey(Note) + + class Meta: + ordering = ['info'] + + def __unicode__(self): + return self.info + class Author(models.Model): name = models.CharField(maxlength=10) num = models.IntegerField(unique=True) + extra = models.ForeignKey(ExtraInfo) def __unicode__(self): return self.name @@ -23,6 +43,10 @@ class Item(models.Model): name = models.CharField(maxlength=10) tags = models.ManyToManyField(Tag, blank=True, null=True) creator = models.ForeignKey(Author) + note = models.ForeignKey(Note) + + class Meta: + ordering = ['-note', 'name'] def __unicode__(self): return self.name @@ -34,6 +58,26 @@ class Report(models.Model): def __unicode__(self): return self.name +class Ranking(models.Model): + rank = models.IntegerField() + author = models.ForeignKey(Author) + + class Meta: + # A complex ordering specification. Should stress the system a bit. + ordering = ('author__extra__note', 'author__name', 'rank') + + def __unicode__(self): + return '%d: %s' % (self.rank, self.author.name) + +class Cover(models.Model): + title = models.CharField(maxlength=50) + item = models.ForeignKey(Item) + + class Meta: + ordering = ['item'] + + def __unicode__(self): + return self.title __test__ = {'API_TESTS':""" >>> t1 = Tag(name='t1') @@ -47,25 +91,38 @@ __test__ = {'API_TESTS':""" >>> t5 = Tag(name='t5', parent=t3) >>> t5.save() +>>> n1 = Note(note='n1') +>>> n1.save() +>>> n2 = Note(note='n2') +>>> n2.save() +>>> n3 = Note(note='n3') +>>> n3.save() ->>> a1 = Author(name='a1', num=1001) +Create these out of order so that sorting by 'id' will be different to sorting +by 'info'. Helps detect some problems later. +>>> e2 = ExtraInfo(info='e2', note=n2) +>>> e2.save() +>>> e1 = ExtraInfo(info='e1', note=n1) +>>> e1.save() + +>>> a1 = Author(name='a1', num=1001, extra=e1) >>> a1.save() ->>> a2 = Author(name='a2', num=2002) +>>> a2 = Author(name='a2', num=2002, extra=e1) >>> a2.save() ->>> a3 = Author(name='a3', num=3003) +>>> a3 = Author(name='a3', num=3003, extra=e2) >>> a3.save() ->>> a4 = Author(name='a4', num=4004) +>>> a4 = Author(name='a4', num=4004, extra=e2) >>> a4.save() ->>> i1 = Item(name='one', creator=a1) +>>> i1 = Item(name='one', creator=a1, note=n3) >>> i1.save() >>> i1.tags = [t1, t2] ->>> i2 = Item(name='two', creator=a2) +>>> i2 = Item(name='two', creator=a2, note=n2) >>> i2.save() >>> i2.tags = [t1, t3] ->>> i3 = Item(name='three', creator=a2) +>>> i3 = Item(name='three', creator=a2, note=n3) >>> i3.save() ->>> i4 = Item(name='four', creator=a4) +>>> i4 = Item(name='four', creator=a4, note=n3) >>> i4.save() >>> i4.tags = [t4] @@ -74,6 +131,20 @@ __test__ = {'API_TESTS':""" >>> r2 = Report(name='r2', creator=a3) >>> r2.save() +Ordering by 'rank' gives us rank2, rank1, rank3. Ordering by the Meta.ordering +will be rank3, rank2, rank1. +>>> rank1 = Ranking(rank=2, author=a2) +>>> rank1.save() +>>> rank2 = Ranking(rank=1, author=a3) +>>> rank2.save() +>>> rank3 = Ranking(rank=3, author=a1) +>>> rank3.save() + +>>> c1 = Cover(title="first", item=i4) +>>> c1.save() +>>> c2 = Cover(title="second", item=i2) +>>> c2.save() + Bug #1050 >>> Item.objects.filter(tags__isnull=True) [<Item: three>] @@ -119,7 +190,7 @@ Bug #1878, #2939 # Create something with a duplicate 'name' so that we can test multi-column # cases (which require some tricky SQL transformations under the covers). ->>> xx = Item(name='four', creator=a2) +>>> xx = Item(name='four', creator=a2, note=n1) >>> xx.save() >>> Item.objects.exclude(name='two').values('creator', 'name').distinct().count() 4 @@ -206,5 +277,40 @@ Bug #2400 Bug #2496 >>> Item.objects.extra(tables=['queries_author']).select_related().order_by('name')[:1] [<Item: four>] + +Bug #2076 +# Ordering on related tables should be possible, even if the table is not +# otherwise involved. +>>> Item.objects.order_by('note__note', 'name') +[<Item: two>, <Item: four>, <Item: one>, <Item: three>] + +# Ordering on a related field should use the remote model's default ordering as +# a final step. +>>> Author.objects.order_by('extra', '-name') +[<Author: a2>, <Author: a1>, <Author: a4>, <Author: a3>] + +# If the remote model does not have a default ordering, we order by its 'id' +# field. +>>> Item.objects.order_by('creator', 'name') +[<Item: one>, <Item: three>, <Item: two>, <Item: four>] + +# Cross model ordering is possible in Meta, too. +>>> Ranking.objects.all() +[<Ranking: 3: a1>, <Ranking: 2: a2>, <Ranking: 1: a3>] +>>> Ranking.objects.all().order_by('rank') +[<Ranking: 1: a3>, <Ranking: 2: a2>, <Ranking: 3: a1>] + +>>> Cover.objects.all() +[<Cover: first>, <Cover: second>] + +Bugs #2874, #3002 +>>> qs = Item.objects.select_related().order_by('note__note', 'name') +>>> list(qs) +[<Item: two>, <Item: four>, <Item: one>, <Item: three>] + +# This is also a good select_related() test because there are multiple Note +# entries in the SQL. The two Note items should be different. +>>> qs[0].note, qs[0].creator.extra.note +(<Note: n2>, <Note: n1>) """} |
