【问题标题】:What's the best way to select an ordered set of django objects by a list of ids?通过 id 列表选择一组有序的 django 对象的最佳方法是什么?
【发布时间】:2012-01-14 15:38:39
【问题描述】:

我有一个来自 Redis 的对象 ID 列表,我想将它们转换为 Django 模型对象(或 QuerySet)列表。结果应该与列表的顺序相同。目前我正在迭代并为每个 id 做一个get。我认为这不是特别有效。

Django 有 in_bulk 但这并没有保留顺序。

列表的大小在 10 到 200 项之间。

【问题讨论】:

  • 您希望它们按 ID 数字排序吗?或者是否有您想要保留的特定订单?
  • 我希望它们按列表的顺序排列。回顾我的问题,它并不明确。已编辑。

标签: django django-models


【解决方案1】:

Manager.in_bulk 只是返回一个字典,所以没有办法强制它有一个特定的顺序。

如果您想要的只是与 ID 列表匹配的对象列表,按 ID 排序,那么请执行以下操作:

id_list = [1, 2, 3, 10, 11, 12]
results = MyModel.objects.filter(id__in=id_list).order_by('id')

它的效率可能不如.in_bulk(),但比一次查询一个要好得多。

但是,如果您想要一个非常具体的顺序 - 说“按照 Redis 返回它们的顺序” - 没有办法让数据库本身这样做。就其性质而言,关系数据库返回一组无序的行,除非您应用排序,但该排序必须基于数据库的字段。

此时,您最好的选择是使用 .in_bulk() 获取对象字典,以 ID 为键,然后查找该字典以按照您需要的顺序构建一个列表:

已编辑:如果您要对结果进行重新排序,则应注意数据库未返回您请求的某些 ID 的可能性。您可以使用 results.get(id, None) 安全地索引到字典中,并使用 filter() 从列表中删除空项目。

id_list = [10, 11, 12, 1, 2, 3]

# Get all of the items from the database
results = MyModel.objects.in_bulk(id_list)

# re-order the results into the order specified by id_list
ordered_results = [results.get(id,None) for id in id_list]

# remove None items from the ordered results
filtered_results = filter(None, ordered_results)

【讨论】:

    【解决方案2】:

    你需要的是in field lookp

    Model.objects.filter(pk__in = id_list)

    【讨论】:

    • 这会保留排序吗?我认为不会。
    • 它没有;它以数据库的自然顺序(或您在模型中定义的任何内容)返回它们——您必须在客户端重新排序;见我上面的回答。
    猜你喜欢
    • 2010-09-27
    • 1970-01-01
    • 2015-01-09
    • 1970-01-01
    • 2018-03-04
    • 1970-01-01
    • 2019-10-26
    • 2012-03-31
    • 2017-04-13
    相关资源
    最近更新 更多