mirror of
https://github.com/django/django.git
synced 2024-12-22 17:16:24 +00:00
Fixed #28335 -- Allowed query expressions in Meta.ordering.
This commit is contained in:
parent
3d2c3905a6
commit
093fd479d6
@ -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.
|
|||||||
|
|
||||||
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.
|
|||||||
|
|
||||||
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
|
|||||||
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):
|
|||||||
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
|
|||||||
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):
|
|||||||
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')
|
||||||
|
)
|
||||||
|
Loading…
Reference in New Issue
Block a user