【问题标题】:Django QuerySet Custom Ordering by IDDjango QuerySet 自定义按 ID 排序
【发布时间】:2011-04-07 05:46:17
【问题描述】:

给定一个 ids/pks 列表,我想生成一个 QuerySet 按列表中的索引排序的对象。

通常我会开始:

pk_list = [5, 9, 2, 14]
queryset = MyModel.objects.filter(pk__in=pk_list)

这当然会返回对象,但是按照模型元排序属性的顺序,我希望按照pk_list中的pks 的顺序获取记录。

最终结果必须是 一个 QuerySet 对象(不是列表),因为我希望将有序的 QuerySet 传递给 Django 的 ModelMultipleChoiceField 表单字段。

【问题讨论】:

标签: python django django-queryset


【解决方案1】:

Django 2.2 中,我能够使用以下方法根据订单列表订购 QuerySet:

pk_list = [4, 23, 10, 9]
preserved = Case(*[When(pk=pk, then=pos) for pos, pk in enumerate(pk_list)])
new_qs = qs.filter(pk__in=pk_list).order_by(preserved)

【讨论】:

    【解决方案2】:

    我不知道如何使用过滤条件来做到这一点。如果您的数据库将按照 IN 子句的顺序返回行,那么您可能可以将 Django 的 extra 方法与您的数据库提供的 ROWNUM 结合使用来实现此目的。 p>

    例如:

    queryset = MyModel.objects.filter(pk__in=[pk_list]).extra(
           select: {'rownum': 'row_num()'}).order_by('rownum')
    

    假设row_num() 是一个返回当前行的行号的数据库函数。 Postgresql 8.4+ 支持row_num(),但我不知道如何使用与IN 子句中的值相同的顺序对返回的行进行排序。

    我认为更好的方法是子类ModelMultipleChoiceField 并在渲染时添加自定义排序逻辑。

    【讨论】:

    • 谢谢你,但我需要一些兼容 sqlite 和 mysql 的东西。我想我会使用MultipleChoiceField 并自己生成选择列表。
    【解决方案3】:

    没有内置的方法可以做到这一点。

    如果您使用的是 MySQL,则可以使用该数据库的 FIELD() 函数在您的模型上设置自定义排序顺序,并按此排序。这会起作用:

    pk_list = [5, 9, 2, 14]
    ordering = 'FIELD(`id`, %s)' % ','.join(str(id) for id in pk_list)
    queryset = MyModel.objects.filter(pk__in=[pk_list]).extra(
                   select={'ordering': ordering}, order_by=('ordering',))
    

    【讨论】:

    • 谢谢你,但我需要一些兼容 sqlite 和 mysql 的东西。我想我会使用MultipleChoiceField 并自己生成选择列表。
    • @amirouche,不,他希望它的顺序与简单的数字排序完全不同。
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2011-02-24
    • 2011-06-22
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多