PageRenderTime 117ms CodeModel.GetById 20ms app.highlight 84ms RepoModel.GetById 1ms app.codeStats 0ms

/tests/regressiontests/queries/tests.py

https://code.google.com/p/mango-py/
Python | 1744 lines | 1284 code | 235 blank | 225 comment | 55 complexity | bb5908ae7a936361e24b1c48b89c858b MD5 | raw file

Large files files are truncated, but you can click here to view the full file

   1import datetime
   2import pickle
   3import sys
   4
   5from django.conf import settings
   6from django.core.exceptions import FieldError
   7from django.db import DatabaseError, connection, connections, DEFAULT_DB_ALIAS
   8from django.db.models import Count
   9from django.db.models.query import Q, ITER_CHUNK_SIZE, EmptyQuerySet
  10from django.test import TestCase, skipUnlessDBFeature
  11from django.utils import unittest
  12from django.utils.datastructures import SortedDict
  13
  14from models import (Annotation, Article, Author, Celebrity, Child, Cover, Detail,
  15    DumbCategory, ExtraInfo, Fan, Item, LeafA, LoopX, LoopZ, ManagedModel,
  16    Member, NamedCategory, Note, Number, Plaything, PointerA, Ranking, Related,
  17    Report, ReservedName, Tag, TvChef, Valid, X, Food, Eaten, Node, ObjectA, ObjectB,
  18    ObjectC)
  19
  20
  21class BaseQuerysetTest(TestCase):
  22    def assertValueQuerysetEqual(self, qs, values):
  23        return self.assertQuerysetEqual(qs, values, transform=lambda x: x)
  24
  25    def assertRaisesMessage(self, exc, msg, func, *args, **kwargs):
  26        try:
  27            func(*args, **kwargs)
  28        except Exception, e:
  29            self.assertEqual(msg, str(e))
  30            self.assertTrue(isinstance(e, exc), "Expected %s, got %s" % (exc, type(e)))
  31        else:
  32            if hasattr(exc, '__name__'):
  33                excName = exc.__name__
  34            else:
  35                excName = str(exc)
  36            raise AssertionError("%s not raised" % excName)
  37
  38
  39class Queries1Tests(BaseQuerysetTest):
  40    def setUp(self):
  41        generic = NamedCategory.objects.create(name="Generic")
  42        self.t1 = Tag.objects.create(name='t1', category=generic)
  43        self.t2 = Tag.objects.create(name='t2', parent=self.t1, category=generic)
  44        self.t3 = Tag.objects.create(name='t3', parent=self.t1)
  45        t4 = Tag.objects.create(name='t4', parent=self.t3)
  46        self.t5 = Tag.objects.create(name='t5', parent=self.t3)
  47
  48        self.n1 = Note.objects.create(note='n1', misc='foo', id=1)
  49        n2 = Note.objects.create(note='n2', misc='bar', id=2)
  50        self.n3 = Note.objects.create(note='n3', misc='foo', id=3)
  51
  52        ann1 = Annotation.objects.create(name='a1', tag=self.t1)
  53        ann1.notes.add(self.n1)
  54        ann2 = Annotation.objects.create(name='a2', tag=t4)
  55        ann2.notes.add(n2, self.n3)
  56
  57        # Create these out of order so that sorting by 'id' will be different to sorting
  58        # by 'info'. Helps detect some problems later.
  59        self.e2 = ExtraInfo.objects.create(info='e2', note=n2)
  60        e1 = ExtraInfo.objects.create(info='e1', note=self.n1)
  61
  62        self.a1 = Author.objects.create(name='a1', num=1001, extra=e1)
  63        self.a2 = Author.objects.create(name='a2', num=2002, extra=e1)
  64        a3 = Author.objects.create(name='a3', num=3003, extra=self.e2)
  65        self.a4 = Author.objects.create(name='a4', num=4004, extra=self.e2)
  66
  67        self.time1 = datetime.datetime(2007, 12, 19, 22, 25, 0)
  68        self.time2 = datetime.datetime(2007, 12, 19, 21, 0, 0)
  69        time3 = datetime.datetime(2007, 12, 20, 22, 25, 0)
  70        time4 = datetime.datetime(2007, 12, 20, 21, 0, 0)
  71        self.i1 = Item.objects.create(name='one', created=self.time1, modified=self.time1, creator=self.a1, note=self.n3)
  72        self.i1.tags = [self.t1, self.t2]
  73        self.i2 = Item.objects.create(name='two', created=self.time2, creator=self.a2, note=n2)
  74        self.i2.tags = [self.t1, self.t3]
  75        self.i3 = Item.objects.create(name='three', created=time3, creator=self.a2, note=self.n3)
  76        i4 = Item.objects.create(name='four', created=time4, creator=self.a4, note=self.n3)
  77        i4.tags = [t4]
  78
  79        self.r1 = Report.objects.create(name='r1', creator=self.a1)
  80        Report.objects.create(name='r2', creator=a3)
  81        Report.objects.create(name='r3')
  82
  83        # Ordering by 'rank' gives us rank2, rank1, rank3. Ordering by the Meta.ordering
  84        # will be rank3, rank2, rank1.
  85        self.rank1 = Ranking.objects.create(rank=2, author=self.a2)
  86
  87        Cover.objects.create(title="first", item=i4)
  88        Cover.objects.create(title="second", item=self.i2)
  89
  90    def test_ticket1050(self):
  91        self.assertQuerysetEqual(
  92            Item.objects.filter(tags__isnull=True),
  93            ['<Item: three>']
  94        )
  95        self.assertQuerysetEqual(
  96            Item.objects.filter(tags__id__isnull=True),
  97            ['<Item: three>']
  98        )
  99
 100    def test_ticket1801(self):
 101        self.assertQuerysetEqual(
 102            Author.objects.filter(item=self.i2),
 103            ['<Author: a2>']
 104        )
 105        self.assertQuerysetEqual(
 106            Author.objects.filter(item=self.i3),
 107            ['<Author: a2>']
 108        )
 109        self.assertQuerysetEqual(
 110            Author.objects.filter(item=self.i2) & Author.objects.filter(item=self.i3),
 111            ['<Author: a2>']
 112        )
 113
 114    def test_ticket2306(self):
 115        # Checking that no join types are "left outer" joins.
 116        query = Item.objects.filter(tags=self.t2).query
 117        self.assertTrue(query.LOUTER not in [x[2] for x in query.alias_map.values()])
 118
 119        self.assertQuerysetEqual(
 120            Item.objects.filter(Q(tags=self.t1)).order_by('name'),
 121            ['<Item: one>', '<Item: two>']
 122        )
 123        self.assertQuerysetEqual(
 124            Item.objects.filter(Q(tags=self.t1)).filter(Q(tags=self.t2)),
 125            ['<Item: one>']
 126        )
 127        self.assertQuerysetEqual(
 128            Item.objects.filter(Q(tags=self.t1)).filter(Q(creator__name='fred')|Q(tags=self.t2)),
 129            ['<Item: one>']
 130        )
 131
 132        # Each filter call is processed "at once" against a single table, so this is
 133        # different from the previous example as it tries to find tags that are two
 134        # things at once (rather than two tags).
 135        self.assertQuerysetEqual(
 136            Item.objects.filter(Q(tags=self.t1) & Q(tags=self.t2)),
 137            []
 138        )
 139        self.assertQuerysetEqual(
 140            Item.objects.filter(Q(tags=self.t1), Q(creator__name='fred')|Q(tags=self.t2)),
 141            []
 142        )
 143
 144        qs = Author.objects.filter(ranking__rank=2, ranking__id=self.rank1.id)
 145        self.assertQuerysetEqual(list(qs), ['<Author: a2>'])
 146        self.assertEqual(2, qs.query.count_active_tables(), 2)
 147        qs = Author.objects.filter(ranking__rank=2).filter(ranking__id=self.rank1.id)
 148        self.assertEqual(qs.query.count_active_tables(), 3)
 149
 150    def test_ticket4464(self):
 151        self.assertQuerysetEqual(
 152            Item.objects.filter(tags=self.t1).filter(tags=self.t2),
 153            ['<Item: one>']
 154        )
 155        self.assertQuerysetEqual(
 156            Item.objects.filter(tags__in=[self.t1, self.t2]).distinct().order_by('name'),
 157            ['<Item: one>', '<Item: two>']
 158        )
 159        self.assertQuerysetEqual(
 160            Item.objects.filter(tags__in=[self.t1, self.t2]).filter(tags=self.t3),
 161            ['<Item: two>']
 162        )
 163
 164        # Make sure .distinct() works with slicing (this was broken in Oracle).
 165        self.assertQuerysetEqual(
 166            Item.objects.filter(tags__in=[self.t1, self.t2]).order_by('name')[:3],
 167            ['<Item: one>', '<Item: one>', '<Item: two>']
 168        )
 169        self.assertQuerysetEqual(
 170            Item.objects.filter(tags__in=[self.t1, self.t2]).distinct().order_by('name')[:3],
 171            ['<Item: one>', '<Item: two>']
 172        )
 173
 174    def test_tickets_2080_3592(self):
 175        self.assertQuerysetEqual(
 176            Author.objects.filter(item__name='one') | Author.objects.filter(name='a3'),
 177            ['<Author: a1>', '<Author: a3>']
 178        )
 179        self.assertQuerysetEqual(
 180            Author.objects.filter(Q(item__name='one') | Q(name='a3')),
 181            ['<Author: a1>', '<Author: a3>']
 182        )
 183        self.assertQuerysetEqual(
 184            Author.objects.filter(Q(name='a3') | Q(item__name='one')),
 185            ['<Author: a1>', '<Author: a3>']
 186        )
 187        self.assertQuerysetEqual(
 188            Author.objects.filter(Q(item__name='three') | Q(report__name='r3')),
 189            ['<Author: a2>']
 190        )
 191
 192    def test_ticket6074(self):
 193        # Merging two empty result sets shouldn't leave a queryset with no constraints
 194        # (which would match everything).
 195        self.assertQuerysetEqual(Author.objects.filter(Q(id__in=[])), [])
 196        self.assertQuerysetEqual(
 197            Author.objects.filter(Q(id__in=[])|Q(id__in=[])),
 198            []
 199        )
 200
 201    def test_tickets_1878_2939(self):
 202        self.assertEqual(Item.objects.values('creator').distinct().count(), 3)
 203
 204        # Create something with a duplicate 'name' so that we can test multi-column
 205        # cases (which require some tricky SQL transformations under the covers).
 206        xx = Item(name='four', created=self.time1, creator=self.a2, note=self.n1)
 207        xx.save()
 208        self.assertEqual(
 209            Item.objects.exclude(name='two').values('creator', 'name').distinct().count(),
 210            4
 211        )
 212        self.assertEqual(
 213            Item.objects.exclude(name='two').extra(select={'foo': '%s'}, select_params=(1,)).values('creator', 'name', 'foo').distinct().count(),
 214            4
 215        )
 216        self.assertEqual(
 217            Item.objects.exclude(name='two').extra(select={'foo': '%s'}, select_params=(1,)).values('creator', 'name').distinct().count(),
 218            4
 219        )
 220        xx.delete()
 221
 222    def test_ticket7323(self):
 223        self.assertEqual(Item.objects.values('creator', 'name').count(), 4)
 224
 225    def test_ticket2253(self):
 226        q1 = Item.objects.order_by('name')
 227        q2 = Item.objects.filter(id=self.i1.id)
 228        self.assertQuerysetEqual(
 229            q1,
 230            ['<Item: four>', '<Item: one>', '<Item: three>', '<Item: two>']
 231        )
 232        self.assertQuerysetEqual(q2, ['<Item: one>'])
 233        self.assertQuerysetEqual(
 234            (q1 | q2).order_by('name'),
 235            ['<Item: four>', '<Item: one>', '<Item: three>', '<Item: two>']
 236        )
 237        self.assertQuerysetEqual((q1 & q2).order_by('name'), ['<Item: one>'])
 238
 239        q1 = Item.objects.filter(tags=self.t1)
 240        q2 = Item.objects.filter(note=self.n3, tags=self.t2)
 241        q3 = Item.objects.filter(creator=self.a4)
 242        self.assertQuerysetEqual(
 243            ((q1 & q2) | q3).order_by('name'),
 244            ['<Item: four>', '<Item: one>']
 245        )
 246
 247    # FIXME: This is difficult to fix and very much an edge case, so punt for
 248    # now.  This is related to the order_by() tests for ticket #2253, but the
 249    # old bug exhibited itself here (q2 was pulling too many tables into the
 250    # combined query with the new ordering, but only because we have evaluated
 251    # q2 already).
 252    @unittest.expectedFailure
 253    def test_order_by_tables(self):
 254        q1 = Item.objects.order_by('name')
 255        q2 = Item.objects.filter(id=self.i1.id)
 256        list(q2)
 257        self.assertEqual(len((q1 & q2).order_by('name').query.tables), 1)
 258
 259    def test_tickets_4088_4306(self):
 260        self.assertQuerysetEqual(
 261            Report.objects.filter(creator=1001),
 262            ['<Report: r1>']
 263        )
 264        self.assertQuerysetEqual(
 265            Report.objects.filter(creator__num=1001),
 266            ['<Report: r1>']
 267        )
 268        self.assertQuerysetEqual(Report.objects.filter(creator__id=1001), [])
 269        self.assertQuerysetEqual(
 270            Report.objects.filter(creator__id=self.a1.id),
 271            ['<Report: r1>']
 272        )
 273        self.assertQuerysetEqual(
 274            Report.objects.filter(creator__name='a1'),
 275            ['<Report: r1>']
 276        )
 277
 278    def test_ticket4510(self):
 279        self.assertQuerysetEqual(
 280            Author.objects.filter(report__name='r1'),
 281            ['<Author: a1>']
 282        )
 283
 284    def test_ticket7378(self):
 285        self.assertQuerysetEqual(self.a1.report_set.all(), ['<Report: r1>'])
 286
 287    def test_tickets_5324_6704(self):
 288        self.assertQuerysetEqual(
 289            Item.objects.filter(tags__name='t4'),
 290            ['<Item: four>']
 291        )
 292        self.assertQuerysetEqual(
 293            Item.objects.exclude(tags__name='t4').order_by('name').distinct(),
 294            ['<Item: one>', '<Item: three>', '<Item: two>']
 295        )
 296        self.assertQuerysetEqual(
 297            Item.objects.exclude(tags__name='t4').order_by('name').distinct().reverse(),
 298            ['<Item: two>', '<Item: three>', '<Item: one>']
 299        )
 300        self.assertQuerysetEqual(
 301            Author.objects.exclude(item__name='one').distinct().order_by('name'),
 302            ['<Author: a2>', '<Author: a3>', '<Author: a4>']
 303        )
 304
 305        # Excluding across a m2m relation when there is more than one related
 306        # object associated was problematic.
 307        self.assertQuerysetEqual(
 308            Item.objects.exclude(tags__name='t1').order_by('name'),
 309            ['<Item: four>', '<Item: three>']
 310        )
 311        self.assertQuerysetEqual(
 312            Item.objects.exclude(tags__name='t1').exclude(tags__name='t4'),
 313            ['<Item: three>']
 314        )
 315
 316        # Excluding from a relation that cannot be NULL should not use outer joins.
 317        query = Item.objects.exclude(creator__in=[self.a1, self.a2]).query
 318        self.assertTrue(query.LOUTER not in [x[2] for x in query.alias_map.values()])
 319
 320        # Similarly, when one of the joins cannot possibly, ever, involve NULL
 321        # values (Author -> ExtraInfo, in the following), it should never be
 322        # promoted to a left outer join. So the following query should only
 323        # involve one "left outer" join (Author -> Item is 0-to-many).
 324        qs = Author.objects.filter(id=self.a1.id).filter(Q(extra__note=self.n1)|Q(item__note=self.n3))
 325        self.assertEqual(
 326            len([x[2] for x in qs.query.alias_map.values() if x[2] == query.LOUTER and qs.query.alias_refcount[x[1]]]),
 327            1
 328        )
 329
 330        # The previous changes shouldn't affect nullable foreign key joins.
 331        self.assertQuerysetEqual(
 332            Tag.objects.filter(parent__isnull=True).order_by('name'),
 333            ['<Tag: t1>']
 334        )
 335        self.assertQuerysetEqual(
 336            Tag.objects.exclude(parent__isnull=True).order_by('name'),
 337            ['<Tag: t2>', '<Tag: t3>', '<Tag: t4>', '<Tag: t5>']
 338        )
 339        self.assertQuerysetEqual(
 340            Tag.objects.exclude(Q(parent__name='t1') | Q(parent__isnull=True)).order_by('name'),
 341            ['<Tag: t4>', '<Tag: t5>']
 342        )
 343        self.assertQuerysetEqual(
 344            Tag.objects.exclude(Q(parent__isnull=True) | Q(parent__name='t1')).order_by('name'),
 345            ['<Tag: t4>', '<Tag: t5>']
 346        )
 347        self.assertQuerysetEqual(
 348            Tag.objects.exclude(Q(parent__parent__isnull=True)).order_by('name'),
 349            ['<Tag: t4>', '<Tag: t5>']
 350        )
 351        self.assertQuerysetEqual(
 352            Tag.objects.filter(~Q(parent__parent__isnull=True)).order_by('name'),
 353            ['<Tag: t4>', '<Tag: t5>']
 354        )
 355
 356    def test_ticket2091(self):
 357        t = Tag.objects.get(name='t4')
 358        self.assertQuerysetEqual(
 359            Item.objects.filter(tags__in=[t]),
 360            ['<Item: four>']
 361        )
 362
 363    def test_heterogeneous_qs_combination(self):
 364        # Combining querysets built on different models should behave in a well-defined
 365        # fashion. We raise an error.
 366        self.assertRaisesMessage(
 367            AssertionError,
 368            'Cannot combine queries on two different base models.',
 369            lambda: Author.objects.all() & Tag.objects.all()
 370        )
 371        self.assertRaisesMessage(
 372            AssertionError,
 373            'Cannot combine queries on two different base models.',
 374            lambda: Author.objects.all() | Tag.objects.all()
 375        )
 376
 377    def test_ticket3141(self):
 378        self.assertEqual(Author.objects.extra(select={'foo': '1'}).count(), 4)
 379        self.assertEqual(
 380            Author.objects.extra(select={'foo': '%s'}, select_params=(1,)).count(),
 381            4
 382        )
 383
 384    def test_ticket2400(self):
 385        self.assertQuerysetEqual(
 386            Author.objects.filter(item__isnull=True),
 387            ['<Author: a3>']
 388        )
 389        self.assertQuerysetEqual(
 390            Tag.objects.filter(item__isnull=True),
 391            ['<Tag: t5>']
 392        )
 393
 394    def test_ticket2496(self):
 395        self.assertQuerysetEqual(
 396            Item.objects.extra(tables=['queries_author']).select_related().order_by('name')[:1],
 397            ['<Item: four>']
 398        )
 399
 400    def test_tickets_2076_7256(self):
 401        # Ordering on related tables should be possible, even if the table is
 402        # not otherwise involved.
 403        self.assertQuerysetEqual(
 404            Item.objects.order_by('note__note', 'name'),
 405            ['<Item: two>', '<Item: four>', '<Item: one>', '<Item: three>']
 406        )
 407
 408        # Ordering on a related field should use the remote model's default
 409        # ordering as a final step.
 410        self.assertQuerysetEqual(
 411            Author.objects.order_by('extra', '-name'),
 412            ['<Author: a2>', '<Author: a1>', '<Author: a4>', '<Author: a3>']
 413        )
 414
 415        # Using remote model default ordering can span multiple models (in this
 416        # case, Cover is ordered by Item's default, which uses Note's default).
 417        self.assertQuerysetEqual(
 418            Cover.objects.all(),
 419            ['<Cover: first>', '<Cover: second>']
 420        )
 421
 422        # If the remote model does not have a default ordering, we order by its 'id'
 423        # field.
 424        self.assertQuerysetEqual(
 425            Item.objects.order_by('creator', 'name'),
 426            ['<Item: one>', '<Item: three>', '<Item: two>', '<Item: four>']
 427        )
 428
 429        # Ordering by a many-valued attribute (e.g. a many-to-many or reverse
 430        # ForeignKey) is legal, but the results might not make sense. That
 431        # isn't Django's problem. Garbage in, garbage out.
 432        self.assertQuerysetEqual(
 433            Item.objects.filter(tags__isnull=False).order_by('tags', 'id'),
 434            ['<Item: one>', '<Item: two>', '<Item: one>', '<Item: two>', '<Item: four>']
 435        )
 436
 437        # If we replace the default ordering, Django adjusts the required
 438        # tables automatically. Item normally requires a join with Note to do
 439        # the default ordering, but that isn't needed here.
 440        qs = Item.objects.order_by('name')
 441        self.assertQuerysetEqual(
 442            qs,
 443            ['<Item: four>', '<Item: one>', '<Item: three>', '<Item: two>']
 444        )
 445        self.assertEqual(len(qs.query.tables), 1)
 446
 447    def test_tickets_2874_3002(self):
 448        qs = Item.objects.select_related().order_by('note__note', 'name')
 449        self.assertQuerysetEqual(
 450            qs,
 451            ['<Item: two>', '<Item: four>', '<Item: one>', '<Item: three>']
 452        )
 453
 454        # This is also a good select_related() test because there are multiple
 455        # Note entries in the SQL. The two Note items should be different.
 456        self.assertTrue(repr(qs[0].note), '<Note: n2>')
 457        self.assertEqual(repr(qs[0].creator.extra.note), '<Note: n1>')
 458
 459    def test_ticket3037(self):
 460        self.assertQuerysetEqual(
 461            Item.objects.filter(Q(creator__name='a3', name='two')|Q(creator__name='a4', name='four')),
 462            ['<Item: four>']
 463        )
 464
 465    def test_tickets_5321_7070(self):
 466        # Ordering columns must be included in the output columns. Note that
 467        # this means results that might otherwise be distinct are not (if there
 468        # are multiple values in the ordering cols), as in this example. This
 469        # isn't a bug; it's a warning to be careful with the selection of
 470        # ordering columns.
 471        self.assertValueQuerysetEqual(
 472            Note.objects.values('misc').distinct().order_by('note', '-misc'),
 473            [{'misc': u'foo'}, {'misc': u'bar'}, {'misc': u'foo'}]
 474        )
 475
 476    def test_ticket4358(self):
 477        # If you don't pass any fields to values(), relation fields are
 478        # returned as "foo_id" keys, not "foo". For consistency, you should be
 479        # able to pass "foo_id" in the fields list and have it work, too. We
 480        # actually allow both "foo" and "foo_id".
 481
 482        # The *_id version is returned by default.
 483        self.assertTrue('note_id' in ExtraInfo.objects.values()[0])
 484
 485        # You can also pass it in explicitly.
 486        self.assertValueQuerysetEqual(
 487            ExtraInfo.objects.values('note_id'),
 488            [{'note_id': 1}, {'note_id': 2}]
 489        )
 490
 491        # ...or use the field name.
 492        self.assertValueQuerysetEqual(
 493            ExtraInfo.objects.values('note'),
 494            [{'note': 1}, {'note': 2}]
 495        )
 496
 497    def test_ticket2902(self):
 498        # Parameters can be given to extra_select, *if* you use a SortedDict.
 499
 500        # (First we need to know which order the keys fall in "naturally" on
 501        # your system, so we can put things in the wrong way around from
 502        # normal. A normal dict would thus fail.)
 503        s = [('a', '%s'), ('b', '%s')]
 504        params = ['one', 'two']
 505        if {'a': 1, 'b': 2}.keys() == ['a', 'b']:
 506            s.reverse()
 507            params.reverse()
 508
 509        # This slightly odd comparison works around the fact that PostgreSQL will
 510        # return 'one' and 'two' as strings, not Unicode objects. It's a side-effect of
 511        # using constants here and not a real concern.
 512        d = Item.objects.extra(select=SortedDict(s), select_params=params).values('a', 'b')[0]
 513        self.assertEqual(d, {'a': u'one', 'b': u'two'})
 514
 515        # Order by the number of tags attached to an item.
 516        l = Item.objects.extra(select={'count': 'select count(*) from queries_item_tags where queries_item_tags.item_id = queries_item.id'}).order_by('-count')
 517        self.assertEqual([o.count for o in l], [2, 2, 1, 0])
 518
 519    def test_ticket6154(self):
 520        # Multiple filter statements are joined using "AND" all the time.
 521
 522        self.assertQuerysetEqual(
 523            Author.objects.filter(id=self.a1.id).filter(Q(extra__note=self.n1)|Q(item__note=self.n3)),
 524            ['<Author: a1>']
 525        )
 526        self.assertQuerysetEqual(
 527                Author.objects.filter(Q(extra__note=self.n1)|Q(item__note=self.n3)).filter(id=self.a1.id),
 528            ['<Author: a1>']
 529        )
 530
 531    def test_ticket6981(self):
 532        self.assertQuerysetEqual(
 533            Tag.objects.select_related('parent').order_by('name'),
 534            ['<Tag: t1>', '<Tag: t2>', '<Tag: t3>', '<Tag: t4>', '<Tag: t5>']
 535        )
 536
 537    def test_ticket9926(self):
 538        self.assertQuerysetEqual(
 539            Tag.objects.select_related("parent", "category").order_by('name'),
 540            ['<Tag: t1>', '<Tag: t2>', '<Tag: t3>', '<Tag: t4>', '<Tag: t5>']
 541        )
 542        self.assertQuerysetEqual(
 543            Tag.objects.select_related('parent', "parent__category").order_by('name'),
 544            ['<Tag: t1>', '<Tag: t2>', '<Tag: t3>', '<Tag: t4>', '<Tag: t5>']
 545        )
 546
 547    def test_tickets_6180_6203(self):
 548        # Dates with limits and/or counts
 549        self.assertEqual(Item.objects.count(), 4)
 550        self.assertEqual(Item.objects.dates('created', 'month').count(), 1)
 551        self.assertEqual(Item.objects.dates('created', 'day').count(), 2)
 552        self.assertEqual(len(Item.objects.dates('created', 'day')), 2)
 553        self.assertEqual(Item.objects.dates('created', 'day')[0], datetime.datetime(2007, 12, 19, 0, 0))
 554
 555    def test_tickets_7087_12242(self):
 556        # Dates with extra select columns
 557        self.assertQuerysetEqual(
 558            Item.objects.dates('created', 'day').extra(select={'a': 1}),
 559            ['datetime.datetime(2007, 12, 19, 0, 0)', 'datetime.datetime(2007, 12, 20, 0, 0)']
 560        )
 561        self.assertQuerysetEqual(
 562            Item.objects.extra(select={'a': 1}).dates('created', 'day'),
 563            ['datetime.datetime(2007, 12, 19, 0, 0)', 'datetime.datetime(2007, 12, 20, 0, 0)']
 564        )
 565
 566        name="one"
 567        self.assertQuerysetEqual(
 568            Item.objects.dates('created', 'day').extra(where=['name=%s'], params=[name]),
 569            ['datetime.datetime(2007, 12, 19, 0, 0)']
 570        )
 571
 572        self.assertQuerysetEqual(
 573            Item.objects.extra(where=['name=%s'], params=[name]).dates('created', 'day'),
 574            ['datetime.datetime(2007, 12, 19, 0, 0)']
 575        )
 576
 577    def test_ticket7155(self):
 578        # Nullable dates
 579        self.assertQuerysetEqual(
 580            Item.objects.dates('modified', 'day'),
 581            ['datetime.datetime(2007, 12, 19, 0, 0)']
 582        )
 583
 584    def test_ticket7098(self):
 585        # Make sure semi-deprecated ordering by related models syntax still
 586        # works.
 587        self.assertValueQuerysetEqual(
 588            Item.objects.values('note__note').order_by('queries_note.note', 'id'),
 589            [{'note__note': u'n2'}, {'note__note': u'n3'}, {'note__note': u'n3'}, {'note__note': u'n3'}]
 590        )
 591
 592    def test_ticket7096(self):
 593        # Make sure exclude() with multiple conditions continues to work.
 594        self.assertQuerysetEqual(
 595            Tag.objects.filter(parent=self.t1, name='t3').order_by('name'),
 596            ['<Tag: t3>']
 597        )
 598        self.assertQuerysetEqual(
 599            Tag.objects.exclude(parent=self.t1, name='t3').order_by('name'),
 600            ['<Tag: t1>', '<Tag: t2>', '<Tag: t4>', '<Tag: t5>']
 601        )
 602        self.assertQuerysetEqual(
 603            Item.objects.exclude(tags__name='t1', name='one').order_by('name').distinct(),
 604            ['<Item: four>', '<Item: three>', '<Item: two>']
 605        )
 606        self.assertQuerysetEqual(
 607            Item.objects.filter(name__in=['three', 'four']).exclude(tags__name='t1').order_by('name'),
 608            ['<Item: four>', '<Item: three>']
 609        )
 610
 611        # More twisted cases, involving nested negations.
 612        self.assertQuerysetEqual(
 613            Item.objects.exclude(~Q(tags__name='t1', name='one')),
 614            ['<Item: one>']
 615        )
 616        self.assertQuerysetEqual(
 617            Item.objects.filter(~Q(tags__name='t1', name='one'), name='two'),
 618            ['<Item: two>']
 619        )
 620        self.assertQuerysetEqual(
 621            Item.objects.exclude(~Q(tags__name='t1', name='one'), name='two'),
 622            ['<Item: four>', '<Item: one>', '<Item: three>']
 623        )
 624
 625    def test_tickets_7204_7506(self):
 626        # Make sure querysets with related fields can be pickled. If this
 627        # doesn't crash, it's a Good Thing.
 628        pickle.dumps(Item.objects.all())
 629
 630    def test_ticket7813(self):
 631        # We should also be able to pickle things that use select_related().
 632        # The only tricky thing here is to ensure that we do the related
 633        # selections properly after unpickling.
 634        qs = Item.objects.select_related()
 635        query = qs.query.get_compiler(qs.db).as_sql()[0]
 636        query2 = pickle.loads(pickle.dumps(qs.query))
 637        self.assertEqual(
 638            query2.get_compiler(qs.db).as_sql()[0],
 639            query
 640        )
 641
 642    def test_deferred_load_qs_pickling(self):
 643        # Check pickling of deferred-loading querysets
 644        qs = Item.objects.defer('name', 'creator')
 645        q2 = pickle.loads(pickle.dumps(qs))
 646        self.assertEqual(list(qs), list(q2))
 647        q3 = pickle.loads(pickle.dumps(qs, pickle.HIGHEST_PROTOCOL))
 648        self.assertEqual(list(qs), list(q3))
 649
 650    def test_ticket7277(self):
 651        self.assertQuerysetEqual(
 652            self.n1.annotation_set.filter(Q(tag=self.t5) | Q(tag__children=self.t5) | Q(tag__children__children=self.t5)),
 653            ['<Annotation: a1>']
 654        )
 655
 656    def test_tickets_7448_7707(self):
 657        # Complex objects should be converted to strings before being used in
 658        # lookups.
 659        self.assertQuerysetEqual(
 660            Item.objects.filter(created__in=[self.time1, self.time2]),
 661            ['<Item: one>', '<Item: two>']
 662        )
 663
 664    def test_ticket7235(self):
 665        # An EmptyQuerySet should not raise exceptions if it is filtered.
 666        q = EmptyQuerySet()
 667        self.assertQuerysetEqual(q.all(), [])
 668        self.assertQuerysetEqual(q.filter(x=10), [])
 669        self.assertQuerysetEqual(q.exclude(y=3), [])
 670        self.assertQuerysetEqual(q.complex_filter({'pk': 1}), [])
 671        self.assertQuerysetEqual(q.select_related('spam', 'eggs'), [])
 672        self.assertQuerysetEqual(q.annotate(Count('eggs')), [])
 673        self.assertQuerysetEqual(q.order_by('-pub_date', 'headline'), [])
 674        self.assertQuerysetEqual(q.distinct(), [])
 675        self.assertQuerysetEqual(
 676            q.extra(select={'is_recent': "pub_date > '2006-01-01'"}),
 677            []
 678        )
 679        q.query.low_mark = 1
 680        self.assertRaisesMessage(
 681            AssertionError,
 682            'Cannot change a query once a slice has been taken',
 683            q.extra, select={'is_recent': "pub_date > '2006-01-01'"}
 684        )
 685        self.assertQuerysetEqual(q.reverse(), [])
 686        self.assertQuerysetEqual(q.defer('spam', 'eggs'), [])
 687        self.assertQuerysetEqual(q.only('spam', 'eggs'), [])
 688
 689    def test_ticket7791(self):
 690        # There were "issues" when ordering and distinct-ing on fields related
 691        # via ForeignKeys.
 692        self.assertEqual(
 693            len(Note.objects.order_by('extrainfo__info').distinct()),
 694            3
 695        )
 696
 697        # Pickling of DateQuerySets used to fail
 698        qs = Item.objects.dates('created', 'month')
 699        _ = pickle.loads(pickle.dumps(qs))
 700
 701    def test_ticket9997(self):
 702        # If a ValuesList or Values queryset is passed as an inner query, we
 703        # make sure it's only requesting a single value and use that as the
 704        # thing to select.
 705        self.assertQuerysetEqual(
 706            Tag.objects.filter(name__in=Tag.objects.filter(parent=self.t1).values('name')),
 707            ['<Tag: t2>', '<Tag: t3>']
 708        )
 709
 710        # Multi-valued values() and values_list() querysets should raise errors.
 711        self.assertRaisesMessage(
 712            TypeError,
 713            'Cannot use a multi-field ValuesQuerySet as a filter value.',
 714            lambda: Tag.objects.filter(name__in=Tag.objects.filter(parent=self.t1).values('name', 'id'))
 715        )
 716        self.assertRaisesMessage(
 717            TypeError,
 718            'Cannot use a multi-field ValuesListQuerySet as a filter value.',
 719            lambda: Tag.objects.filter(name__in=Tag.objects.filter(parent=self.t1).values_list('name', 'id'))
 720        )
 721
 722    def test_ticket9985(self):
 723        # qs.values_list(...).values(...) combinations should work.
 724        self.assertValueQuerysetEqual(
 725            Note.objects.values_list("note", flat=True).values("id").order_by("id"),
 726            [{'id': 1}, {'id': 2}, {'id': 3}]
 727        )
 728        self.assertQuerysetEqual(
 729            Annotation.objects.filter(notes__in=Note.objects.filter(note="n1").values_list('note').values('id')),
 730            ['<Annotation: a1>']
 731        )
 732
 733    def test_ticket10205(self):
 734        # When bailing out early because of an empty "__in" filter, we need
 735        # to set things up correctly internally so that subqueries can continue properly.
 736        self.assertEqual(Tag.objects.filter(name__in=()).update(name="foo"), 0)
 737
 738    def test_ticket10432(self):
 739        # Testing an empty "__in" filter with a generator as the value.
 740        def f():
 741            return iter([])
 742        n_obj = Note.objects.all()[0]
 743        def g():
 744            for i in [n_obj.pk]:
 745                yield i
 746        self.assertQuerysetEqual(Note.objects.filter(pk__in=f()), [])
 747        self.assertEqual(list(Note.objects.filter(pk__in=g())), [n_obj])
 748
 749    def test_ticket10742(self):
 750        # Queries used in an __in clause don't execute subqueries
 751
 752        subq = Author.objects.filter(num__lt=3000)
 753        qs = Author.objects.filter(pk__in=subq)
 754        self.assertQuerysetEqual(qs, ['<Author: a1>', '<Author: a2>'])
 755
 756        # The subquery result cache should not be populated
 757        self.assertTrue(subq._result_cache is None)
 758
 759        subq = Author.objects.filter(num__lt=3000)
 760        qs = Author.objects.exclude(pk__in=subq)
 761        self.assertQuerysetEqual(qs, ['<Author: a3>', '<Author: a4>'])
 762
 763        # The subquery result cache should not be populated
 764        self.assertTrue(subq._result_cache is None)
 765
 766        subq = Author.objects.filter(num__lt=3000)
 767        self.assertQuerysetEqual(
 768            Author.objects.filter(Q(pk__in=subq) & Q(name='a1')),
 769            ['<Author: a1>']
 770        )
 771
 772        # The subquery result cache should not be populated
 773        self.assertTrue(subq._result_cache is None)
 774
 775    def test_ticket7076(self):
 776        # Excluding shouldn't eliminate NULL entries.
 777        self.assertQuerysetEqual(
 778            Item.objects.exclude(modified=self.time1).order_by('name'),
 779            ['<Item: four>', '<Item: three>', '<Item: two>']
 780        )
 781        self.assertQuerysetEqual(
 782            Tag.objects.exclude(parent__name=self.t1.name),
 783            ['<Tag: t1>', '<Tag: t4>', '<Tag: t5>']
 784        )
 785
 786    def test_ticket7181(self):
 787        # Ordering by related tables should accomodate nullable fields (this
 788        # test is a little tricky, since NULL ordering is database dependent.
 789        # Instead, we just count the number of results).
 790        self.assertEqual(len(Tag.objects.order_by('parent__name')), 5)
 791
 792        # Empty querysets can be merged with others.
 793        self.assertQuerysetEqual(
 794            Note.objects.none() | Note.objects.all(),
 795            ['<Note: n1>', '<Note: n2>', '<Note: n3>']
 796        )
 797        self.assertQuerysetEqual(
 798            Note.objects.all() | Note.objects.none(),
 799            ['<Note: n1>', '<Note: n2>', '<Note: n3>']
 800        )
 801        self.assertQuerysetEqual(Note.objects.none() & Note.objects.all(), [])
 802        self.assertQuerysetEqual(Note.objects.all() & Note.objects.none(), [])
 803
 804    def test_ticket9411(self):
 805        # Make sure bump_prefix() (an internal Query method) doesn't (re-)break. It's
 806        # sufficient that this query runs without error.
 807        qs = Tag.objects.values_list('id', flat=True).order_by('id')
 808        qs.query.bump_prefix()
 809        first = qs[0]
 810        self.assertEqual(list(qs), range(first, first+5))
 811
 812    def test_ticket8439(self):
 813        # Complex combinations of conjunctions, disjunctions and nullable
 814        # relations.
 815        self.assertQuerysetEqual(
 816            Author.objects.filter(Q(item__note__extrainfo=self.e2)|Q(report=self.r1, name='xyz')),
 817            ['<Author: a2>']
 818        )
 819        self.assertQuerysetEqual(
 820            Author.objects.filter(Q(report=self.r1, name='xyz')|Q(item__note__extrainfo=self.e2)),
 821            ['<Author: a2>']
 822        )
 823        self.assertQuerysetEqual(
 824            Annotation.objects.filter(Q(tag__parent=self.t1)|Q(notes__note='n1', name='a1')),
 825            ['<Annotation: a1>']
 826        )
 827        xx = ExtraInfo.objects.create(info='xx', note=self.n3)
 828        self.assertQuerysetEqual(
 829            Note.objects.filter(Q(extrainfo__author=self.a1)|Q(extrainfo=xx)),
 830            ['<Note: n1>', '<Note: n3>']
 831        )
 832        xx.delete()
 833        q = Note.objects.filter(Q(extrainfo__author=self.a1)|Q(extrainfo=xx)).query
 834        self.assertEqual(
 835            len([x[2] for x in q.alias_map.values() if x[2] == q.LOUTER and q.alias_refcount[x[1]]]),
 836            1
 837        )
 838
 839
 840class Queries2Tests(TestCase):
 841    def setUp(self):
 842        Number.objects.create(num=4)
 843        Number.objects.create(num=8)
 844        Number.objects.create(num=12)
 845
 846    def test_ticket4289(self):
 847        # A slight variation on the restricting the filtering choices by the
 848        # lookup constraints.
 849        self.assertQuerysetEqual(Number.objects.filter(num__lt=4), [])
 850        self.assertQuerysetEqual(Number.objects.filter(num__gt=8, num__lt=12), [])
 851        self.assertQuerysetEqual(
 852            Number.objects.filter(num__gt=8, num__lt=13),
 853            ['<Number: 12>']
 854        )
 855        self.assertQuerysetEqual(
 856            Number.objects.filter(Q(num__lt=4) | Q(num__gt=8, num__lt=12)),
 857            []
 858        )
 859        self.assertQuerysetEqual(
 860            Number.objects.filter(Q(num__gt=8, num__lt=12) | Q(num__lt=4)),
 861            []
 862        )
 863        self.assertQuerysetEqual(
 864            Number.objects.filter(Q(num__gt=8) & Q(num__lt=12) | Q(num__lt=4)),
 865            []
 866        )
 867        self.assertQuerysetEqual(
 868            Number.objects.filter(Q(num__gt=7) & Q(num__lt=12) | Q(num__lt=4)),
 869            ['<Number: 8>']
 870        )
 871
 872    def test_ticket12239(self):
 873        # Float was being rounded to integer on gte queries on integer field.  Tests
 874        # show that gt, lt, gte, and lte work as desired.  Note that the fix changes
 875        # get_prep_lookup for gte and lt queries only.
 876        self.assertQuerysetEqual(
 877            Number.objects.filter(num__gt=11.9),
 878            ['<Number: 12>']
 879        )
 880        self.assertQuerysetEqual(Number.objects.filter(num__gt=12), [])
 881        self.assertQuerysetEqual(Number.objects.filter(num__gt=12.0), [])
 882        self.assertQuerysetEqual(Number.objects.filter(num__gt=12.1), [])
 883        self.assertQuerysetEqual(
 884            Number.objects.filter(num__lt=12),
 885            ['<Number: 4>', '<Number: 8>']
 886        )
 887        self.assertQuerysetEqual(
 888            Number.objects.filter(num__lt=12.0),
 889            ['<Number: 4>', '<Number: 8>']
 890        )
 891        self.assertQuerysetEqual(
 892            Number.objects.filter(num__lt=12.1),
 893            ['<Number: 4>', '<Number: 8>', '<Number: 12>']
 894        )
 895        self.assertQuerysetEqual(
 896            Number.objects.filter(num__gte=11.9),
 897            ['<Number: 12>']
 898        )
 899        self.assertQuerysetEqual(
 900            Number.objects.filter(num__gte=12),
 901            ['<Number: 12>']
 902        )
 903        self.assertQuerysetEqual(
 904            Number.objects.filter(num__gte=12.0),
 905            ['<Number: 12>']
 906        )
 907        self.assertQuerysetEqual(Number.objects.filter(num__gte=12.1), [])
 908        self.assertQuerysetEqual(Number.objects.filter(num__gte=12.9), [])
 909        self.assertQuerysetEqual(
 910            Number.objects.filter(num__lte=11.9),
 911            ['<Number: 4>', '<Number: 8>']
 912        )
 913        self.assertQuerysetEqual(
 914            Number.objects.filter(num__lte=12),
 915            ['<Number: 4>', '<Number: 8>', '<Number: 12>']
 916        )
 917        self.assertQuerysetEqual(
 918            Number.objects.filter(num__lte=12.0),
 919            ['<Number: 4>', '<Number: 8>', '<Number: 12>']
 920        )
 921        self.assertQuerysetEqual(
 922            Number.objects.filter(num__lte=12.1),
 923            ['<Number: 4>', '<Number: 8>', '<Number: 12>']
 924        )
 925        self.assertQuerysetEqual(
 926            Number.objects.filter(num__lte=12.9),
 927            ['<Number: 4>', '<Number: 8>', '<Number: 12>']
 928        )
 929
 930    def test_ticket7411(self):
 931        # Saving to db must work even with partially read result set in another
 932        # cursor.
 933        for num in range(2 * ITER_CHUNK_SIZE + 1):
 934            _ = Number.objects.create(num=num)
 935
 936        for i, obj in enumerate(Number.objects.all()):
 937            obj.save()
 938            if i > 10: break
 939
 940    def test_ticket7759(self):
 941        # Count should work with a partially read result set.
 942        count = Number.objects.count()
 943        qs = Number.objects.all()
 944        def run():
 945            for obj in qs:
 946                return qs.count() == count
 947        self.assertTrue(run())
 948
 949
 950class Queries3Tests(BaseQuerysetTest):
 951    def test_ticket7107(self):
 952        # This shouldn't create an infinite loop.
 953        self.assertQuerysetEqual(Valid.objects.all(), [])
 954
 955    def test_ticket8683(self):
 956        # Raise proper error when a DateQuerySet gets passed a wrong type of
 957        # field
 958        self.assertRaisesMessage(
 959            AssertionError,
 960            "'name' isn't a DateField.",
 961            Item.objects.dates, 'name', 'month'
 962        )
 963
 964class Queries4Tests(BaseQuerysetTest):
 965    def setUp(self):
 966        generic = NamedCategory.objects.create(name="Generic")
 967        self.t1 = Tag.objects.create(name='t1', category=generic)
 968
 969        n1 = Note.objects.create(note='n1', misc='foo', id=1)
 970        n2 = Note.objects.create(note='n2', misc='bar', id=2)
 971
 972        e1 = ExtraInfo.objects.create(info='e1', note=n1)
 973        e2 = ExtraInfo.objects.create(info='e2', note=n2)
 974
 975        self.a1 = Author.objects.create(name='a1', num=1001, extra=e1)
 976        self.a3 = Author.objects.create(name='a3', num=3003, extra=e2)
 977
 978        self.r1 = Report.objects.create(name='r1', creator=self.a1)
 979        self.r2 = Report.objects.create(name='r2', creator=self.a3)
 980        self.r3 = Report.objects.create(name='r3')
 981
 982        Item.objects.create(name='i1', created=datetime.datetime.now(), note=n1, creator=self.a1)
 983        Item.objects.create(name='i2', created=datetime.datetime.now(), note=n1, creator=self.a3)
 984
 985    def test_ticket14876(self):
 986        q1 = Report.objects.filter(Q(creator__isnull=True) | Q(creator__extra__info='e1'))
 987        q2 = Report.objects.filter(Q(creator__isnull=True)) | Report.objects.filter(Q(creator__extra__info='e1'))
 988        self.assertQuerysetEqual(q1, ["<Report: r1>", "<Report: r3>"])
 989        self.assertEqual(str(q1.query), str(q2.query))
 990
 991        q1 = Report.objects.filter(Q(creator__extra__info='e1') | Q(creator__isnull=True))
 992        q2 = Report.objects.filter(Q(creator__extra__info='e1')) | Report.objects.filter(Q(creator__isnull=True))
 993        self.assertQuerysetEqual(q1, ["<Report: r1>", "<Report: r3>"])
 994        self.assertEqual(str(q1.query), str(q2.query))
 995
 996        q1 = Item.objects.filter(Q(creator=self.a1) | Q(creator__report__name='r1')).order_by()
 997        q2 = Item.objects.filter(Q(creator=self.a1)).order_by() | Item.objects.filter(Q(creator__report__name='r1')).order_by()
 998        self.assertQuerysetEqual(q1, ["<Item: i1>"])
 999        self.assertEqual(str(q1.query), str(q2.query))
1000
1001        q1 = Item.objects.filter(Q(creator__report__name='e1') | Q(creator=self.a1)).order_by()
1002        q2 = Item.objects.filter(Q(creator__report__name='e1')).order_by() | Item.objects.filter(Q(creator=self.a1)).order_by()
1003        self.assertQuerysetEqual(q1, ["<Item: i1>"])
1004        self.assertEqual(str(q1.query), str(q2.query))
1005
1006    def test_ticket7095(self):
1007        # Updates that are filtered on the model being updated are somewhat
1008        # tricky in MySQL. This exercises that case.
1009        ManagedModel.objects.create(data='mm1', tag=self.t1, public=True)
1010        self.assertEqual(ManagedModel.objects.update(data='mm'), 1)
1011
1012        # A values() or values_list() query across joined models must use outer
1013        # joins appropriately.
1014        # Note: In Oracle, we expect a null CharField to return u'' instead of
1015        # None.
1016        if connection.features.interprets_empty_strings_as_nulls:
1017            expected_null_charfield_repr = u''
1018        else:
1019            expected_null_charfield_repr = None
1020        self.assertValueQuerysetEqual(
1021            Report.objects.values_list("creator__extra__info", flat=True).order_by("name"),
1022            [u'e1', u'e2', expected_null_charfield_repr],
1023        )
1024
1025        # Similarly for select_related(), joins beyond an initial nullable join
1026        # must use outer joins so that all results are included.
1027        self.assertQuerysetEqual(
1028            Report.objects.select_related("creator", "creator__extra").order_by("name"),
1029            ['<Report: r1>', '<Report: r2>', '<Report: r3>']
1030        )
1031
1032        # When there are multiple paths to a table from another table, we have
1033        # to be careful not to accidentally reuse an inappropriate join when
1034        # using select_related(). We used to return the parent's Detail record
1035        # here by mistake.
1036
1037        d1 = Detail.objects.create(data="d1")
1038        d2 = Detail.objects.create(data="d2")
1039        m1 = Member.objects.create(name="m1", details=d1)
1040        m2 = Member.objects.create(name="m2", details=d2)
1041        Child.objects.create(person=m2, parent=m1)
1042        obj = m1.children.select_related("person__details")[0]
1043        self.assertEqual(obj.person.details.data, u'd2')
1044
1045    def test_order_by_resetting(self):
1046        # Calling order_by() with no parameters removes any existing ordering on the
1047        # model. But it should still be possible to add new ordering after that.
1048        qs = Author.objects.order_by().order_by('name')
1049        self.assertTrue('ORDER BY' in qs.query.get_compiler(qs.db).as_sql()[0])
1050
1051    def test_ticket10181(self):
1052        # Avoid raising an EmptyResultSet if an inner query is probably
1053        # empty (and hence, not executed).
1054        self.assertQuerysetEqual(
1055            Tag.objects.filter(id__in=Tag.objects.filter(id__in=[])),
1056            []
1057        )
1058
1059
1060class Queries5Tests(TestCase):
1061    def setUp(self):
1062        # Ordering by 'rank' gives us rank2, rank1, rank3. Ordering by the Meta.ordering
1063        # will be rank3, rank2, rank1.
1064        n1 = Note.objects.create(note='n1', misc='foo', id=1)
1065        n2 = Note.objects.create(note='n2', misc='bar', id=2)
1066        e1 = ExtraInfo.objects.create(info='e1', note=n1)
1067        e2 = ExtraInfo.objects.create(info='e2', note=n2)
1068        a1 = Author.objects.create(name='a1', num=1001, extra=e1)
1069        a2 = Author.objects.create(name='a2', num=2002, extra=e1)
1070        a3 = Author.objects.create(name='a3', num=3003, extra=e2)
1071        self.rank1 = Ranking.objects.create(rank=2, author=a2)
1072        Ranking.objects.create(rank=1, author=a3)
1073        Ranking.objects.create(rank=3, author=a1)
1074
1075    def test_ordering(self):
1076        # Cross model ordering is possible in Meta, too.
1077        self.assertQuerysetEqual(
1078            Ranking.objects.all(),
1079            ['<Ranking: 3: a1>', '<Ranking: 2: a2>', '<Ranking: 1: a3>']
1080        )
1081        self.assertQuerysetEqual(
1082            Ranking.objects.all().order_by('rank'),
1083            ['<Ranking: 1: a3>', '<Ranking: 2: a2>', '<Ranking: 3: a1>']
1084        )
1085
1086
1087        # Ordering of extra() pieces is possible, too and you can mix extra
1088        # fields and model fields in the ordering.
1089        self.assertQuerysetEqual(
1090            Ranking.objects.extra(tables=['django_site'], order_by=['-django_site.id', 'rank']),
1091            ['<Ranking: 1: a3>', '<Ranking: 2: a2>', '<Ranking: 3: a1>']
1092        )
1093
1094        qs = Ranking.objects.extra(select={'good': 'case when rank > 2 then 1 else 0 end'})
1095        self.assertEqual(
1096            [o.good for o in qs.extra(order_by=('-good',))],
1097            [True, False, False]
1098        )
1099        self.assertQuerysetEqual(
1100            qs.extra(order_by=('-good', 'id')),
1101            ['<Ranking: 3: a1>', '<Ranking: 2: a2>', '<Ranking: 1: a3>']
1102        )
1103
1104        # Despite having some extra aliases in the query, we can still omit
1105        # them in a values() query.
1106        dicts = qs.values('id', 'rank').order_by('id')
1107        self.assertEqual(
1108            [d.items()[1] for d in dicts],
1109            [('rank', 2), ('rank', 1), ('rank', 3)]
1110        )
1111
1112    def test_ticket7256(self):
1113        # An empty values() call includes all aliases, including those from an
1114        # extra()
1115        qs = Ranking.objects.extra(select={'good': 'case when rank > 2 then 1 else 0 end'})
1116        dicts = qs.values().order_by('id')
1117        for d in dicts: del d['id']; del d['author_id']
1118        self.assertEqual(
1119            [sorted(d.items()) for d in dicts],
1120            [[('good', 0), ('rank', 2)], [('good', 0), ('rank', 1)], [('good', 1), ('rank', 3)]]
1121        )
1122
1123    def test_ticket7045(self):
1124        # Extra tables used to crash SQL construction on the second use.
1125        qs = Ranking.objects.extra(tables=['django_site'])
1126        qs.query.get_compiler(qs.db).as_sql()
1127        # test passes if this doesn't raise an exception.
1128        qs.query.get_compiler(qs.db).as_sql()
1129
1130    def test_ticket9848(self):
1131        # Make sure that updates which only filter on sub-tables don't
1132        # inadvertently update the wrong records (bug #9848).
1133
1134        # Make sure that the IDs from different tables don't happen to match.
1135        self.assertQuerysetEqual(
1136            Ranking.objects.filter(author__name='a1'),
1137            ['<Ranking: 3: a1>']
1138        )
1139        self.assertEqual(
1140            Ranking.objects.filter(author__name='a1').update(rank='4'),
1141            1
1142        )
1143        r = Ranking.objects.filter(author__name='a1')[0]
1144        self.assertNotEqual(r.id, r.author.id)
1145        self.assertEqual(r.rank, 4)
1146        r.rank = 3
1147        r.save()
1148        self.assertQuerysetEqual(
1149            Ranking.objects.all(),
1150            ['<Ranking: 3: a1>', '<Ranking: 2: a2>', '<Ranking: 1: a3>']
1151        )
1152
1153    def test_ticket5261(self):
1154        self.assertQuerysetEqual(
1155            Note.objects.exclude(Q()),
1156            ['<Note: n1>', '<Note: n2>']
1157        )
1158
1159
1160class SelectRelatedTests(TestCase):
1161    def test_tickets_3045_3288(self):
1162        # Once upon a time, select_related() with circular relations would loop
1163        # infinitely if you forgot to specify "depth". Now we set an arbitrary
1164        # default upper bound.
1165        self.assertQuerysetEqual(X.objects.all(), [])
1166        self.assertQuerysetEqual(X.objects.select_related(), [])
1167
1168
1169class SubclassFKTests(TestCase):
1170    def test_ticket7778(self):
1171        # Model subclasses could not be deleted if a nullable foreign key
1172        # relates to a model that relates back.
1173
1174        num_celebs = Celebrity.objects.count()
1175        tvc = TvChef.objects.create(name="Huey")
1176        self.assertEqual(Celebrity.objects.count(), num_celebs + 1)
1177        Fan.objects.create(fan_of=tvc)
1178        Fan.objects.create(fan_of=tvc)
1179        tvc.delete()
1180
1181        # The parent object should have been deleted as well.
1182        self.assertEqual(Celebrity.objects.count(), num_celebs)
1183
1184
1185class CustomPkTests(TestCase):
1186    def test_ticket7371(self):
1187        self.assertQuerysetEqual(Related.objects.order_by('custom'), [])
1188
1189
1190class NullableRelOrderingTests(TestCase):
1191    def test_ticket10028(self):
1192        # Ordering by model related to nullable relations(!) should use outer
1193        # joins, so that all results are included.
1194        _ = Plaything.objects.create(name="p1")
1195        self.assertQuerysetEqual(
1196            Plaything.objects.all(),
1197            ['<Plaything: p1>']
1198        )
1199
1200
1201class DisjunctiveFilterTests(TestCase):
1202    def setUp(self):
1203        self.n1 = Note.objects.create(note='n1', misc='foo', id=1)
1204        ExtraInfo.objects.create(info='e1', note=self.n1)
1205
1206    def test_ticket7872(self):
1207        # Another variation on the disjunct…

Large files files are truncated, but you can click here to view the full file