Django自定义order_by

Art*_*r C 5 python django sql-order-by

我有一个模型,例如.带外键的汽车,例如.所有者,可能是空白也可能不是空白.汽车有一个creation_date.

我想按日期订购这些车,但如果车有车主,则必须取车主的出生日期而不是车的creation_date.

这可能吗?

Tim*_*ony 5

看看这个类似的问题:排序查询集的好方法? - Django

您不能使用模型的Meta ordering,因为它只接受一个字段

https://docs.djangoproject.com/en/dev/ref/models/options/#ordering

您不能使用该查询order_by('creation_date', 'birthdate'),因为只有它们具有相同的生日日期才会对其进行排序creation_date

因此,您可以编写一个自定义管理器来为您添加自定义排序.

import operator
class CarManager(models.Manager):
    def get_query_set(self):
        auths = super(CarManager, self).get_query_set().all().order_by('-creation')
        ordered = sorted(auths, key=operator.attrgetter('birthday'))
        return ordered

class Car(models.Model):
    sorted = CarManager()
Run Code Online (Sandbox Code Playgroud)

所以你现在可以查询:

Car.sorted.all()
Run Code Online (Sandbox Code Playgroud)

获取已排序汽车的所有查询集

  • 不要忘记使用`list()`:`list().通过调用list()来强制评估QuerySet.但是要注意,这可能会产生很大的内存开销,因为Django会将列表中的每个元素加载到内存中.相反,迭代QuerySet将利用您的数据库加载数据并仅在您需要时实例化对象.[Django doc](https://docs.djangoproject.com/en/dev/ref/models/querysets /#当-查询集-被评估) (3认同)

cat*_*ran 5

这可以通过回退到SQL:

Car.objects.filter(...).extra(select={'odate': '''
  if(owner_id,
     (select date_of_birth from owner_table where id=owner_id),
     creation_date
  )
'''}).order_by('odate')
Run Code Online (Sandbox Code Playgroud)

if函数是特定于MySQL的.对于SQLite或Postgres,您应该使用case语句.