【问题标题】:Django custom order_byDjango 自定义 order_by
【发布时间】:2011-11-28 23:48:53
【问题描述】:

我有一个模型,例如。带外键的汽车,例如。所有者,可能为空,也可能不为空。 汽车有一个创建日期。

我想按日期订购这些汽车,但如果汽车有车主,则必须使用车主的出生日期而不是汽车的创建日期。

这可能吗?

【问题讨论】:

    标签: python django sql-order-by


    【解决方案1】:

    这可以通过回退到 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 语句。

    【讨论】:

    • Django 被设计为独立于数据库,所以我更喜欢 Timmy 的解决方案。还是谢谢!
    【解决方案2】:

    看看这个类似的问题:Good ways to sort a queryset? - Django

    你不能使用模型的元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()
    

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

    【讨论】:

    • 我用过这个,效果很好!我在自定义管理器中定义了一个函数,在其中我将查询集转换为使用 list() 的列表,然后使用 car.date 作为键进行插入排序。 get_date 是我的 Car 模型中的一个方法,它返回所有者的出生日期或汽车的创建日期。我后来将 car.date 定义为属性(get_date)。谢谢!
    • 别忘了小心list(): list(). Force evaluation of a QuerySet by calling list() on it. Be warned, though, that this could have a large memory overhead, because Django will load each element of the list into memory. In contrast, iterating over a QuerySet will take advantage of your database to load data and instantiate objects only as you need them. Django doc
    【解决方案3】:

    您可以编写一个返回适当日期的方法(如果汽车有所有者返回生日,否则返回创建日期)然后 order your model based on this method.

    【讨论】:

    • 这似乎是最简单的解决方案。但是你给出的例子是总和的注释,一个聚合函数。我想用我自己的函数注释它。
    猜你喜欢
    • 2016-04-06
    • 1970-01-01
    • 2010-11-02
    • 2022-09-28
    • 1970-01-01
    • 2016-08-07
    • 1970-01-01
    • 1970-01-01
    • 2019-12-20
    相关资源
    最近更新 更多