summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorMalcolm Tredinnick <malcolm.tredinnick@gmail.com>2007-10-15 00:29:27 +0000
committerMalcolm Tredinnick <malcolm.tredinnick@gmail.com>2007-10-15 00:29:27 +0000
commit201c15dcb62543ea66ff66858be088340ed50221 (patch)
tree3a128b0e7448b2d498a36efd95ef9bd71cb37ba9
parenta1d160e2ea22cb010b276cfc2a085f9cd3d81b22 (diff)
queryset-refactor: Added an order_by parameter to extra(). Refs #2076.
git-svn-id: http://code.djangoproject.com/svn/django/branches/queryset-refactor@6511 bcc190cf-cafb-0310-a4f2-bffc1f526a37
-rw-r--r--django/db/models/query.py9
-rw-r--r--django/db/models/sql/query.py15
-rw-r--r--tests/regressiontests/queries/models.py11
3 files changed, 24 insertions, 11 deletions
diff --git a/django/db/models/query.py b/django/db/models/query.py
index a39220a1b1..25febd6d88 100644
--- a/django/db/models/query.py
+++ b/django/db/models/query.py
@@ -313,11 +313,10 @@ class _QuerySet(object):
obj.query.distinct = true_or_false
return obj
- def extra(self, select=None, where=None, params=None, tables=None):
+ def extra(self, select=None, where=None, params=None, tables=None,
+ order_by=None):
"""
- Add extra SQL fragments to the query. These are applied more or less
- verbatim (no quoting, no alias renaming, etc), so care should be taken
- when using extra() with other complex filters and combinations.
+ Add extra SQL fragments to the query.
"""
assert self.query.can_filter(), \
"Cannot change a query once a slice has been taken"
@@ -330,6 +329,8 @@ class _QuerySet(object):
clone.query.extra_params.extend(params)
if tables:
clone.query.extra_tables.extend(tables)
+ if order_by:
+ clone.query.extra_order_by.extend(order_by)
return clone
###################
diff --git a/django/db/models/sql/query.py b/django/db/models/sql/query.py
index 35c6cc28dc..5d96ec8020 100644
--- a/django/db/models/sql/query.py
+++ b/django/db/models/sql/query.py
@@ -378,9 +378,14 @@ class Query(object):
for alias in self.tables:
if not self.alias_map[alias][ALIAS_REFCOUNT]:
continue
- name, alias, join_type, lhs, lhs_col, col = \
- self.alias_map[alias][ALIAS_JOIN]
- alias_str = (alias != name and ' AS %s' % alias or '')
+ join = self.alias_map[alias][ALIAS_JOIN]
+ if join:
+ name, alias, join_type, lhs, lhs_col, col = join
+ alias_str = (alias != name and ' AS %s' % alias or '')
+ else:
+ join_type = None
+ alias_str = ''
+ name = alias
if join_type:
result.append('%s %s%s ON (%s.%s = %s.%s)'
% (join_type, qn(name), alias_str, qn(lhs),
@@ -464,8 +469,8 @@ class Query(object):
def find_ordering_name(self, name, opts, alias=None, default_order='ASC'):
"""
- Returns the table alias (the name might not be unambiguous, the alias
- will be) and column name for ordering by the given 'name' parameter.
+ Returns the table alias (the name might be ambiguous, the alias will
+ not be) and column name for ordering by the given 'name' parameter.
The 'name' is of the form 'field1__field2__...__fieldN'.
"""
name, order = get_order_dir(name, default_order)
diff --git a/tests/regressiontests/queries/models.py b/tests/regressiontests/queries/models.py
index c775772ada..d47792ecaa 100644
--- a/tests/regressiontests/queries/models.py
+++ b/tests/regressiontests/queries/models.py
@@ -289,6 +289,11 @@ Bug #2076
>>> Author.objects.order_by('extra', '-name')
[<Author: a2>, <Author: a1>, <Author: a4>, <Author: a3>]
+# Using remote model default ordering can span multiple models (in this case,
+# Cover is ordered by Item's default, which uses Note's default).
+>>> Cover.objects.all()
+[<Cover: first>, <Cover: second>]
+
# If the remote model does not have a default ordering, we order by its 'id'
# field.
>>> Item.objects.order_by('creator', 'name')
@@ -300,8 +305,10 @@ Bug #2076
>>> Ranking.objects.all().order_by('rank')
[<Ranking: 1: a3>, <Ranking: 2: a2>, <Ranking: 3: a1>]
->>> Cover.objects.all()
-[<Cover: first>, <Cover: second>]
+# Ordering of extra() pieces is possible, too and you can mix extra fields and
+# model fields in the ordering.
+>>> Ranking.objects.extra(tables=['django_site'], order_by=['-django_site.id', 'rank'])
+[<Ranking: 1: a3>, <Ranking: 2: a2>, <Ranking: 3: a1>]
Bugs #2874, #3002
>>> qs = Item.objects.select_related().order_by('note__note', 'name')