【问题标题】:How to sort a Django QuerySet by (field, custom function, field)如何按(字段、自定义函数、字段)对 Django QuerySet 进行排序
【发布时间】:2014-02-20 11:19:31
【问题描述】:

我正在寻找一个按 field1、function、field2 排序的 QuerySet。

型号:

class Task(models.Model):
    issue_id = models.CharField(max_length=20, unique=True)
    title = models.CharField(max_length=100)
    priority_id = models.IntegerField(blank=True, null=True)
    created_date = models.DateTimeField(auto_now_add=True)

    def due_date(self):
        ...
        return ageing

我正在寻找类似的东西:

taskList = Task.objects.all().order_by('priority_id', ***duedate***, 'title')

显然,您不能通过自定义函数对查询集进行排序。有什么建议吗?

【问题讨论】:

    标签: python django


    【解决方案1】:

    由于实际排序发生在不使用 Python 的数据库中,因此您不能使用 Python 函数进行排序。您需要在 SQL 表达式中实现到期日期逻辑,作为 Queryset.extra(select={...}) 计算字段,类似于:

    due_date_expr = '(implementation of your logic in SQL)'
    taskList = Task.objects.all().extra(select={'due_date': due_date_expr}).order_by('priority_id', 'due_date', 'title')
    

    如果您的逻辑过于复杂,您可能需要将其实现为数据库中的存储过程。

    或者,如果您的数据集非常小(例如,几十到几百条记录),您可以在一个列表中获取整个结果集并在事后对其进行排序:

    taskList = list(Task.objects.all())
    taskList.sort(cmp=comparison_function) // or .sort(key=key_function)
    

    【讨论】:

    • 不错的答案。所以要么在SQL端处理,要么在Python端处理。
    【解决方案2】:

    @lanzz 的答案,虽然看起来是正确的,但对我没有用,但来自另一个线程的这个答案对我来说很有魔力:

    https://stackoverflow.com/a/37648265/6420686

    from django.db.models import Case, When
    
    ids = [list of ids]
    preserved = Case(*[When(id=pk, then=pos) for pos, pk in enumerate(ids)])
    filtered_users = User.objects \
        .filter(id__in=ids) \
        .order_by(preserved)
    

    【讨论】:

      【解决方案3】:

      如果查询集不太大,可以在 Python 中使用排序:

      ordered = sorted(Task.objects.all(), key=lambda o: (o.priority_id, o.due_date(), o.title))
      

      【讨论】:

      • 感谢您的回答。但这不会变成 order_by(duedate, title) -- 没有 priority_id 吗?
      猜你喜欢
      • 1970-01-01
      • 2011-05-09
      • 2017-03-17
      • 1970-01-01
      • 1970-01-01
      • 2017-07-30
      • 2011-01-11
      • 1970-01-01
      相关资源
      最近更新 更多