Django自定义order_by

7 投票
3 回答
15916 浏览
提问于 2025-04-17 03:29

我有一个模型,比如说“汽车”,它有一个外键,比如说“车主”,这个外键可能是空的,也可能有值。

汽车还有一个创建日期。

我想按照日期来排序这些汽车,但如果汽车有车主的话,就要用车主的出生日期来代替汽车的创建日期进行排序。

这样做可以吗?

3 个回答

1

你可以写一个方法,这个方法会根据情况返回合适的日期。如果车子有主人,就返回主人的生日;如果没有主人,就返回创建日期。然后你可以根据这个方法来对你的模型进行排序。

6

这可以通过使用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')

if这个函数是MySQL特有的。如果你使用的是SQLite或Postgres数据库,就应该用case语句。

6

看看这个类似的问题:在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()

这样你就可以查询:

Car.sorted.all()

来获取所有排序后的汽车查询集。

撰写回答