Changeset 7285
- Timestamp:
- 03/18/08 05:21:50 (5 months ago)
- Files:
-
- django/branches/queryset-refactor/django/db/models/sql/datastructures.py (modified) (1 diff)
- django/branches/queryset-refactor/django/db/models/sql/query.py (modified) (5 diffs)
- django/branches/queryset-refactor/docs/db-api.txt (modified) (1 diff)
- django/branches/queryset-refactor/tests/regressiontests/queries/models.py (modified) (1 diff)
Legend:
- Unmodified
- Added
- Removed
- Modified
- Copied
- Moved
django/branches/queryset-refactor/django/db/models/sql/datastructures.py
r7235 r7285 10 10 pass 11 11 12 class JoinError(Exception): 12 class MultiJoin(Exception): 13 """ 14 Used by join construction code to indicate the point at which a 15 multi-valued join was attempted (if the caller wants to treat that 16 exceptionally). 17 """ 13 18 def __init__(self, level): 14 19 self.level = level django/branches/queryset-refactor/django/db/models/sql/query.py
r7283 r7285 19 19 from django.db.models.fields import FieldDoesNotExist 20 20 from django.core.exceptions import FieldError 21 from datastructures import EmptyResultSet, Empty, JoinError21 from datastructures import EmptyResultSet, Empty, MultiJoin 22 22 from constants import * 23 23 … … 524 524 if not alias: 525 525 alias = self.get_initial_alias() 526 try: 527 field, target, opts, joins, last = self.setup_joins(pieces, opts, 528 alias, False, False) 529 except JoinError: 530 raise FieldError("Cannot order by many-valued field: '%s'" % name) 526 field, target, opts, joins, last = self.setup_joins(pieces, opts, 527 alias, False) 531 528 alias = joins[-1] 532 529 col = target.column … … 849 846 field, target, opts, join_list, last = self.setup_joins(parts, opts, 850 847 alias, (connector == AND), allow_many) 851 except JoinError, e:848 except MultiJoin, e: 852 849 self.split_exclude(filter_expr, LOOKUP_SEP.join(parts[:e.level])) 853 850 return … … 1008 1005 for alias in joins: 1009 1006 self.unref_alias(alias) 1010 raise JoinError(pos + 1)1007 raise MultiJoin(pos + 1) 1011 1008 if model: 1012 1009 # The field lives on a base class of the current model. … … 1176 1173 True) 1177 1174 self.select.append((joins[-1], target.column)) 1178 except JoinError:1175 except MultiJoin: 1179 1176 raise FieldError("Invalid field name: '%s'" % name) 1180 1177 django/branches/queryset-refactor/docs/db-api.txt
r7230 r7285 511 511 ...since the ``Blog`` model has no default ordering specified. 512 512 513 You can only order by model fields that have a single value attached to them 514 for each instance of the model. For example, non-relations, ``ForeignKey`` and 515 ``OneToOneField`` fields. Explicitly, you can't order by a ``ManyToManyField`` 516 or a reverse ``ForeignKey`` relation. There's no naturally correct ordering 517 for many-valued fields and a lot of the alternatives are not psosible to 518 express in SQL very efficiently. 513 It is permissible to specify a multi-valued field to order the results by (for 514 example, a ``ManyToMany`` field). Normally this won't be a sensible thing to 515 do and it's really an advanced usage feature. However, if you know that your 516 queryset's filtering or available data implies that there will only be one 517 ordering piece of data for each of the main items you are selecting, the 518 ordering may well be exactly what you want to do. Use ordering on multi-valued 519 fields with care and make sure the results are what you expect. 519 520 520 521 **New in Django development version:** If you don't want any ordering to be django/branches/queryset-refactor/tests/regressiontests/queries/models.py
r7247 r7285 425 425 426 426 # Ordering by a many-valued attribute (e.g. a many-to-many or reverse 427 # ForeignKey) doesn't make sense (there's no natural ordering). 427 # ForeignKey) is legal, but the results might not make sense. That isn't 428 # Django's problem. Garbage in, garbage out. 428 429 >>> Item.objects.all().order_by('tags') 429 Traceback (most recent call last): 430 ... 431 FieldError: Cannot order by many-valued field: 'tags' 430 [...] 432 431 433 432 # If we replace the default ordering, Django adjusts the required tables
