Kaydet (Commit) 093fd479 authored tarafından Dima Kudosh's avatar Dima Kudosh Kaydeden (comit) Tim Graham

Fixed #28335 -- Allowed query expressions in Meta.ordering.

üst 3d2c3905
...@@ -1553,8 +1553,8 @@ class Model(metaclass=ModelBase): ...@@ -1553,8 +1553,8 @@ class Model(metaclass=ModelBase):
errors = [] errors = []
fields = cls._meta.ordering fields = cls._meta.ordering
# Skip '?' fields. # Skip expressions and '?' fields.
fields = (f for f in fields if f != '?') fields = (f for f in fields if isinstance(f, str) and f != '?')
# Convert "-field" to "field". # Convert "-field" to "field".
fields = ((f[1:] if f.startswith('-') else f) for f in fields) fields = ((f[1:] if f.startswith('-') else f) for f in fields)
......
...@@ -256,9 +256,10 @@ Django quotes column and table names behind the scenes. ...@@ -256,9 +256,10 @@ Django quotes column and table names behind the scenes.
ordering = ['-order_date'] ordering = ['-order_date']
This is a tuple or list of strings. Each string is a field name with an optional This is a tuple or list of strings and/or query expressions. Each string is
"-" prefix, which indicates descending order. Fields without a leading "-" will a field name with an optional "-" prefix, which indicates descending order.
be ordered ascending. Use the string "?" to order randomly. Fields without a leading "-" will be ordered ascending. Use the string "?"
to order randomly.
For example, to order by a ``pub_date`` field ascending, use this:: For example, to order by a ``pub_date`` field ascending, use this::
...@@ -272,9 +273,20 @@ Django quotes column and table names behind the scenes. ...@@ -272,9 +273,20 @@ Django quotes column and table names behind the scenes.
ordering = ['-pub_date', 'author'] ordering = ['-pub_date', 'author']
You can also use :doc:`query expressions </ref/models/expressions>`. To
order by ``author`` ascending and make null values sort last, use this::
from django.db.models import F
ordering = [F('author').asc(nulls_last=True)]
Default ordering also affects :ref:`aggregation queries Default ordering also affects :ref:`aggregation queries
<aggregation-ordering-interaction>`. <aggregation-ordering-interaction>`.
.. versionchanged:: 2.0
Support for query expressions was added.
.. warning:: .. warning::
Ordering is not a free operation. Each field you add to the ordering Ordering is not a free operation. Each field you add to the ordering
......
...@@ -283,6 +283,9 @@ Models ...@@ -283,6 +283,9 @@ Models
different conditionals <conditional-aggregation>` to multiple aggregations different conditionals <conditional-aggregation>` to multiple aggregations
over the same fields or relations. over the same fields or relations.
* Added support for expressions in :attr:`Meta.ordering
<django.db.models.Options.ordering>`.
Requests and Responses Requests and Responses
~~~~~~~~~~~~~~~~~~~~~~ ~~~~~~~~~~~~~~~~~~~~~~
......
...@@ -42,6 +42,12 @@ class OrderedByAuthorArticle(Article): ...@@ -42,6 +42,12 @@ class OrderedByAuthorArticle(Article):
ordering = ('author', 'second_author') ordering = ('author', 'second_author')
class OrderedByFArticle(Article):
class Meta:
proxy = True
ordering = (models.F('author').asc(nulls_first=True), 'id')
class Reference(models.Model): class Reference(models.Model):
article = models.ForeignKey(OrderedByAuthorArticle, models.CASCADE) article = models.ForeignKey(OrderedByAuthorArticle, models.CASCADE)
......
...@@ -5,7 +5,7 @@ from django.db.models import F ...@@ -5,7 +5,7 @@ from django.db.models import F
from django.db.models.functions import Upper from django.db.models.functions import Upper
from django.test import TestCase from django.test import TestCase
from .models import Article, Author, Reference from .models import Article, Author, OrderedByFArticle, Reference
class OrderingTests(TestCase): class OrderingTests(TestCase):
...@@ -368,3 +368,13 @@ class OrderingTests(TestCase): ...@@ -368,3 +368,13 @@ class OrderingTests(TestCase):
r1 = Reference.objects.create(article_id=self.a1.pk) r1 = Reference.objects.create(article_id=self.a1.pk)
r2 = Reference.objects.create(article_id=self.a2.pk) r2 = Reference.objects.create(article_id=self.a2.pk)
self.assertSequenceEqual(Reference.objects.all(), [r2, r1]) self.assertSequenceEqual(Reference.objects.all(), [r2, r1])
def test_default_ordering_by_f_expression(self):
"""F expressions can be used in Meta.ordering."""
articles = OrderedByFArticle.objects.all()
articles.filter(headline='Article 2').update(author=self.author_2)
articles.filter(headline='Article 3').update(author=self.author_1)
self.assertQuerysetEqual(
articles, ['Article 1', 'Article 4', 'Article 3', 'Article 2'],
attrgetter('headline')
)
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment