Django QuerySet attributes之order_by()基础用法以及如何传递打包排序参数

本文详细介绍了Django QuerySet的order_by方法,包括默认排序、动态构造排序参数、跨模型排序以及如何避免清除先前的排序设置。还提供了如何向order_by传递打包排序参数的实例,确保在项目中的正确使用。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

本文分为两部分:

  • 官网相关部分文档
  • 展示如何向order_by传递打包排序参数【项目中的实际使用情景】

官网相关部分文档

官网文档中的用法只涉及一般用法,适用于参数固定或者静态参情景,对于动态构造后面我会进行补充

order_by(*fields)¶

By default, results returned by a QuerySet are ordered by the ordering tuple given by the ordering option in the model’s Meta. You can override this on a per-QuerySet basis by using the order_by method.

默认情况下QuerySet的返回值是一个由定义模型时在Meta中给定的排序元组按序作用的结果,但是我们可以在每一个QuerySet的基上调用order_by方法重写这一行为。
class Answer(models.Model):
    question = models.ForeignKey(Question, on_delete=models.CASCADE)
    # ...

    class Meta:
        ordering = ['-pub_date', 'author']
        #注意这里,排序参数前如果有‘-’则代表着降序,没有则默认升序
        #To order by pub_date descending, then by author ascending, use this:

you can also use query 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)]

Regular example:

Entry.objects.filter(pub_date__year=2005).order_by('-pub_date', 'headline')#多静态参/固定参

The result above will be ordered by pub_date descending, then by headline ascending. The negative sign in front of “-pub_date” indicates descending order. Ascending order is implied. To order randomly, use “?”, like so:

Entry.objects.order_by('?')#此方法一般不用,消耗太高,影响性能

Note: order_by(‘?’) queries may be expensive and slow, depending on the database backend you’re using.

To order by a field in a different model, use the same syntax as when you are querying across model relations. That is, the name of the field, followed by a double underscore (__), followed by the name of the field in the new model, and so on for as many models as you want to join. For example:

Entry.objects.order_by('blog__name', 'headline')

If you try to order by a field that is a relation to another model, Django will use the default ordering on the related model, or order by the related model’s primary key if there is no Meta.ordering specified. For example, since the Blog model has no default ordering specified:

Entry.objects.order_by('blog')

…is identical to:

Entry.objects.order_by('blog__id')

If Blog had ordering = [‘name’], then the first queryset would be identical to:

Entry.objects.order_by('blog__name')

You can also order by query expressions by calling asc() or desc() on the expression:

Entry.objects.order_by(Coalesce('summary', 'headline').desc())

Be cautious when ordering by fields in related models if you are also using distinct(). See the note in distinct() for an explanation of how related model ordering can change the expected results.

Note

It is permissible to specify a multi-valued field to order the results by (for example, a ManyToManyField field, or the reverse relation of a ForeignKey field).

Consider this case:

class Event(Model):
   parent = models.ForeignKey(
       'self',
       on_delete=models.CASCADE,
       related_name='children',
   )
   date = models.DateField()

Event.objects.order_by('children__date')
Here, there could potentially be multiple ordering data for each Event; each Event with multiple children will be returned multiple times into the new QuerySet that order_by() creates. In other words, using order_by() on the QuerySet could return more items than you were working on to begin with - which is probably neither expected nor useful.

Thus, take care when using multi-valued field to order the results. If you can be sure that there will only be one ordering piece of data for each of the items you’re ordering, this approach should not present problems. If not, make sure the results are what you expect.

There’s no way to specify whether ordering should be case sensitive. With respect to case-sensitivity, Django will order results however your database backend normally orders them.

You can order by a field converted to lowercase with Lower which will achieve case-consistent ordering:

Entry.objects.order_by(Lower('headline').desc())

If you don’t want any ordering to be applied to a query, not even the default ordering, call order_by() with no parameters.

You can tell if a query is ordered or not by checking the QuerySet.ordered attribute, which will be True if the QuerySet has been ordered in any way.

Each order_by() call will clear any previous ordering. For example, this query will be ordered by pub_date and not headline:

Entry.objects.order_by('headline').order_by('pub_date')

注意

对于上例中对order_by的链式调用只会对最后一个排序条件生效,如果想要依次生效那么需要使用如下方式:

Entry.objects.filter(pub_date__year=2005).order_by('-pub_date', 'headline')

Warning

Ordering is not a free operation. Each field you add to the ordering incurs a cost to your database. Each foreign key you add will implicitly include all of its default orderings as well.

If a query doesn’t have an ordering specified, results are returned from the database in an unspecified order. A particular ordering is guaranteed only when ordering by a set of fields that uniquely identify each object in the results. For example, if a name field isn’t unique, ordering by it won’t guarantee objects with the same name always appear in the same order.

官网相关部分链接

https://docs.djangoproject.com/en/2.0/ref/models/querysets/#django.db.models.query.QuerySet.order_by

https://docs.djangoproject.com/en/2.0/ref/models/options/#django.db.models.Options.ordering

向order_by传递打包排序参数

此部分内容也是我今天项目中用到然后上网查询学习的,亲测无误!stackoverflow问答链接

下面展示如何使用:

1、首先定义一个函数来对参数进行打包

def sorts():
    sort = ['bedrooms', 'bathrooms']
    return sort

2、然后调用打包函数得到打包参数:

posts = Post.objects.filter(**keyword_args).order_by(*sorts())
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值