Ticket #2076: ticket-2076.5.diff
File ticket-2076.5.diff, 13.1 KB (added by , 18 years ago) |
---|
-
.5/django/core/management.py
diff -rN -u old-ticket2076.5/django/core/management.py new-ticket2076.5/django/core/management.py
old new 1033 1033 field_name = field_name[1:] 1034 1034 if opts.order_with_respect_to and field_name == '_order': 1035 1035 continue 1036 if '.' in field_name: continue # Skip ordering in the format 'table.field'. 1036 if '.' in field_name: # Reject ordering in the format 'table.field'. 1037 e.add(opts, '"ordering" has "%s" which uses a format not supported anymore. Use field names and \'__\' instead.' % field_name) 1038 if '__' in field_name: continue # Skip ordering in the format 'relation__related_model_field'. 1037 1039 try: 1038 1040 opts.get_field(field_name, many_to_many=False) 1039 1041 except models.FieldDoesNotExist: -
.5/django/db/models/query.py
diff -rN -u old-ticket2076.5/django/db/models/query.py new-ticket2076.5/django/db/models/query.py
old new 471 471 where.extend(where2) 472 472 params.extend(params2) 473 473 474 # Resolve order_by dependencies before joins to order by related tables 475 order_by = [] 476 if self._order_by is not None: # use order_by = () to disable ordering 477 ordering_to_use = self._order_by 478 else: 479 ordering_to_use = opts.ordering 480 481 for f in handle_legacy_orderlist(ordering_to_use): 482 if "." in f: # dot-style field, fall back to old ordering code below 483 order_by = [] 484 break 485 elif f == '?': # Special case. 486 order_by.append(backend.get_random_function_sql()) 487 break 488 elif f.startswith('-'): 489 path = f[1:].split(LOOKUP_SEPARATOR) 490 order = "DESC" 491 else: 492 path = f.split(LOOKUP_SEPARATOR) 493 order = "ASC" 494 495 joins3, where3, params3 = lookup_inner(path, 'exact', False, opts, opts.db_table, None) 496 joins.update(joins3) 497 498 # hack to get fieldname to order by. modify lookup_inner to supply this instead. 499 field = where3[0].replace(' = %s', '') 500 order_by.append('%s %s' % (field, order)) 501 474 502 # Add additional tables and WHERE clauses based on select_related. 475 503 if self._select_related: 476 504 fill_table_cache(opts, select, tables, where, opts.db_table, [opts.db_table]) … … 496 524 sql.append(where and "WHERE " + " AND ".join(where)) 497 525 498 526 # ORDER BY clause 499 order_by = []500 527 if self._order_by is not None: 501 528 ordering_to_use = self._order_by 502 529 else: 503 530 ordering_to_use = opts.ordering 531 if order_by: # dont try to set up ordering again if already done 532 ordering_to_use = [] 504 533 for f in handle_legacy_orderlist(ordering_to_use): 505 if f == '?': # Special case. 506 order_by.append(backend.get_random_function_sql()) 534 if f.startswith('-'): 535 col_name = f[1:] 536 order = "DESC" 537 else: 538 col_name = f 539 order = "ASC" 540 # Use the database table as a column prefix if it wasn't given, 541 # and if the requested column isn't a custom SELECT. 542 if col_name not in (self._select or ()): 543 table_prefix = backend.quote_name(opts.db_table) + '.' 507 544 else: 508 if f.startswith('-'): 509 col_name = f[1:] 510 order = "DESC" 511 else: 512 col_name = f 513 order = "ASC" 514 if "." in col_name: 515 table_prefix, col_name = col_name.split('.', 1) 516 table_prefix = backend.quote_name(table_prefix) + '.' 517 else: 518 # Use the database table as a column prefix if it wasn't given, 519 # and if the requested column isn't a custom SELECT. 520 if "." not in col_name and col_name not in (self._select or ()): 521 table_prefix = backend.quote_name(opts.db_table) + '.' 522 else: 523 table_prefix = '' 524 order_by.append('%s%s %s' % (table_prefix, backend.quote_name(orderfield2column(col_name, opts)), order)) 545 table_prefix = '' 546 order_by.append('%s%s %s' % (table_prefix, backend.quote_name(orderfield2column(col_name, opts)), order)) 525 547 if order_by: 526 548 sql.append("ORDER BY " + ", ".join(order_by)) 527 549 -
.5/docs/db-api.txt
diff -rN -u old-ticket2076.5/docs/db-api.txt new-ticket2076.5/docs/db-api.txt
old new 420 420 421 421 Entry.objects.order_by('?') 422 422 423 To order by a field in a different table, add the other table's name and a dot, 424 like so:: 423 To order by a field in a related model, use the relationship name and the field 424 name separated by ``__`` (that's a double-underscore) using a notation that 425 resembles the notation used in `Field lookups`_:: 425 426 426 Entry.objects.order_by('blogs_blog.name', 'headline') 427 Entry.objects.order_by('blog__name', 'headline') 428 429 This can also span several ForeignKey and ManyToMany relationships both forward 430 and reverse:: 431 432 Blog.objects.order_by('entry_set__authors__name') 427 433 428 434 There's no way to specify whether ordering should be case sensitive. With 429 435 respect to case-sensitivity, Django will order results however your database -
.5/tests/modeltests/ordering/models.py
diff -rN -u old-ticket2076.5/tests/modeltests/ordering/models.py new-ticket2076.5/tests/modeltests/ordering/models.py
old new 11 11 12 12 The ordering attribute is not required. If you leave it off, ordering will be 13 13 undefined -- not random, just undefined. 14 15 This also applies for models that have a relationship to another model, you 16 can use the name of the related field just like you'd any other field to 17 specify ordering of the model instances in the ``Meta.ordering`` attribute or 18 the ``order_by`` queryset method. 19 20 Another feature is that you can even order by a field of the related model, 21 for this you use a notation similar to the one used in field lookup, that is 22 ``relationname__fieldname`` (that's a double-underscore). 14 23 """ 15 24 16 25 from django.db import models … … 24 33 def __str__(self): 25 34 return self.headline 26 35 36 class ReaderLetter(models.Model): 37 article = models.ForeignKey(Article, null=True) 38 reader_name = models.CharField(maxlength=100) 39 date_sent = models.DateTimeField() 40 class Meta: 41 ordering = ('reader_name',) 42 43 def __str__(self): 44 if self.article is None: 45 return self.reader_name 46 else: 47 return "%s, %s" % (self.reader_name, self.article) 48 49 class EditorResponse(models.Model): 50 reader_letter = models.ForeignKey(ReaderLetter) 51 editor_name = models.CharField(maxlength=100) 52 class Meta: 53 ordering = ('editor_name',) 54 55 def __str__(self): 56 return "%s, %s" % (self.editor_name, self.reader_letter) 57 58 class Reporter(models.Model): 59 name = models.CharField(maxlength=30) 60 articles = models.ManyToManyField(Article) 61 class Meta: 62 ordering = ('articles__headline',) 63 64 def __str__(self): 65 r = "%s" % (self.name) 66 if self.articles.count(): 67 r += '; articles: %s' % ', '.join([str(a) for a in self.articles.all()]) 68 return r 69 27 70 __test__ = {'API_TESTS':""" 28 71 # Create a couple of Articles. 29 72 >>> from datetime import datetime … … 64 107 # don't know what order the output will be in. 65 108 >>> Article.objects.order_by('?') 66 109 [...] 110 111 # Create some reader letters. 112 # First the ones sent as comments about some article. 113 >>> rl1 = ReaderLetter.objects.create(reader_name='Reader D', article=a1, date_sent=(datetime(2005, 8, 5))) 114 >>> rl2 = ReaderLetter.objects.create(reader_name='Reader D', article=a2, date_sent=(datetime(2005, 8, 4))) 115 >>> rl3 = ReaderLetter.objects.create(reader_name='Reader C', article=a4, date_sent=(datetime(2005, 8, 3))) 116 >>> rl4 = ReaderLetter.objects.create(reader_name='Reader B', article=a4, date_sent=(datetime(2005, 8, 2))) 117 >>> rl5 = ReaderLetter.objects.create(reader_name='Reader A', article=None, date_sent=(datetime(2005, 8, 1))) 118 119 # By default ReaderLetter.objects.all() orders by the name 120 # of the reader that wrote it ascending. 121 >>> ReaderLetter.objects.all() 122 [<ReaderLetter: Reader A>, <ReaderLetter: Reader B, Article 4>, <ReaderLetter: Reader C, Article 4>, <ReaderLetter: Reader D, Article 1>, <ReaderLetter: Reader D, Article 2>] 123 124 # Composite ordering using the related article headline descending as one of the components 125 >>> ReaderLetter.objects.order_by('reader_name', '-article__headline') 126 [<ReaderLetter: Reader B, Article 4>, <ReaderLetter: Reader C, Article 4>, <ReaderLetter: Reader D, Article 2>, <ReaderLetter: Reader D, Article 1>] 127 128 >>> er1 = EditorResponse.objects.create(editor_name='Editor A', reader_letter=rl1) 129 >>> er2 = EditorResponse.objects.create(editor_name='Editor B', reader_letter=rl2) 130 >>> er3 = EditorResponse.objects.create(editor_name='Editor B', reader_letter=rl3) 131 132 >>> EditorResponse.objects.all() 133 [<EditorResponse: Editor A, Reader D, Article 1>, <EditorResponse: Editor B, Reader D, Article 2>, <EditorResponse: Editor B, Reader C, Article 4>] 134 135 # Order just by the relationship field, this should order by the natural 136 # ordering of the ReaderLetter model (i.e. as dictated by its Meta.ordering), 137 # but right now is ordering by the ReaderLetter PK. 138 >>> EditorResponse.objects.order_by('reader_letter') 139 [<EditorResponse: Editor A, Reader D, Article 1>, <EditorResponse: Editor B, Reader D, Article 2>, <EditorResponse: Editor B, Reader C, Article 4>] 140 141 # Order by another field of the related ReaderLetter object. 142 >>> EditorResponse.objects.order_by('reader_letter__reader_name') 143 [<EditorResponse: Editor B, Reader C, Article 4>, <EditorResponse: Editor A, Reader D, Article 1>, <EditorResponse: Editor B, Reader D, Article 2>] 144 145 # The ordering specification can span models through relationships too. 146 # Order by the PK of the article related to the reader letter related 147 # to the editor response, descending. 148 >>> EditorResponse.objects.order_by('-reader_letter__article') 149 [<EditorResponse: Editor B, Reader C, Article 4>, <EditorResponse: Editor B, Reader D, Article 2>, <EditorResponse: Editor A, Reader D, Article 1>] 150 151 # Order by the article publication date, ascending. 152 >>> EditorResponse.objects.order_by('reader_letter__article__pub_date') 153 [<EditorResponse: Editor A, Reader D, Article 1>, <EditorResponse: Editor B, Reader D, Article 2>, <EditorResponse: Editor B, Reader C, Article 4>] 154 155 # Composite ordering with one of the components being a specification that 156 # spans a FK relationship 157 >>> EditorResponse.objects.order_by('-editor_name', 'reader_letter__article') 158 [<EditorResponse: Editor B, Reader D, Article 2>, <EditorResponse: Editor B, Reader C, Article 4>, <EditorResponse: Editor A, Reader D, Article 1>] 159 160 # Test many-to-many relationships 161 >>> r1 = Reporter.objects.create(name='John') 162 >>> r2 = Reporter.objects.create(name='Jane') 163 >>> r3 = Reporter.objects.create(name='Paul') 164 165 >>> r1.articles = [a1, a2] 166 >>> r2.articles = [a4, a3] 167 >>> r3.articles = [a4, a2] 168 169 # The natural ordering of the Reporter model as dictated by its 170 # `Meta.ordering` option is by 'article__headline' (i.e. by a field of a 171 # related model) 172 >>> Reporter.objects.all().distinct() 173 [<Reporter: John; articles: Article 2, Article 1>, <Reporter: Paul; articles: Article 4, Article 2>, <Reporter: Jane; articles: Article 4, Article 3>] 174 175 # Order by a ManyToMany relationship. Remember the Article model natural 176 # ordering as dictated by its `Meta.ordering` option is 177 # ('-pub_date', 'headline') 178 >>> Reporter.objects.distinct().order_by('articles') 179 [<Reporter: John; articles: Article 2, Article 1>, <Reporter: Paul; articles: Article 4, Article 2>, <Reporter: Jane; articles: Article 4, Article 3>] 180 181 # Order the reporters by the headlines of the articles they contributed 182 # to, descending 183 >>> Reporter.objects.distinct().order_by('-articles__headline') 184 [<Reporter: Jane; articles: Article 4, Article 3>, <Reporter: Paul; articles: Article 4, Article 2>, <Reporter: John; articles: Article 2, Article 1>] 185 186 # Note how the ordering can also span reverse relationships. We are ordering 187 # the reporters by the date the letter in response to the articles she/he 188 # contributed to was sent (if any) 189 >>> Reporter.objects.distinct().order_by('articles__readerletter__date_sent') 190 [<Reporter: Jane; articles: Article 4, Article 3>, <Reporter: Paul; articles: Article 4, Article 2>, <Reporter: John; articles: Article 2, Article 1>] 191 67 192 """}