如何按指定顺序获取 Django 模型实例

胖芳大大_2091

胖芳大大_2091

2026-06-24

578人浏览

原创

如何按指定顺序获取 Django 模型实例

在 Django 中,当需要根据给定的 ID 或字段值列表(如护照号)精确控制查询结果的返回顺序时,直接使用 __in 查询无法保证顺序;本文介绍三种可靠方案:union() 构造有序 SQL、Python 层 sorted() 重排,以及推荐的数据库级 CASE WHEN 排序。

在 django 中,当需要根据给定的 id 或字段值列表(如护照号)精确控制查询结果的返回顺序时,直接使用 `__in` 查询无法保证顺序;本文介绍三种可靠方案:`union()` 构造有序 sql、python 层 `sorted()` 重排,以及推荐的数据库级 `case when` 排序。

在 Django 开发中,一个常见但易被忽视的需求是:按 Python 列表中定义的特定顺序,获取对应的数据库模型实例。例如,你有一组护照号 ['AA1111111', 'AD2222222', 'AA3333333', ...],希望查询出的 User 对象严格遵循该顺序——而非数据库默认的任意排列。然而,像 User.objects.filter(passport_number__in=lst) 这样的写法虽能正确筛选数据,却不带 ORDER BY 子句,因此结果顺序由数据库引擎决定(可能依赖索引结构),不可预测。

✅ 方案一:使用 union() 实现 SQL 级顺序(推荐用于小列表)

Django 的 .union() 方法可将多个独立查询以 UNION 方式拼接,天然保留子查询的执行顺序(注意:需加 all=True 避免去重):

from django.db.models import Q

lst = ['AA1111111', 'AD2222222', 'AA3333333', 'AA4444444', 'АВ5555555']

# 构建按顺序排列的 QuerySet
queryset = User.objects.none().union(
    *[User.objects.filter(passport_number=p) for p in lst],
    all=True
)

生成的 SQL 类似:

SELECT * FROM user WHERE passport_number = 'AA1111111'
UNION ALL
SELECT * FROM user WHERE passport_number = 'AD2222222'
-- ...

✅ 优势:纯数据库操作,支持后续链式调用(如 .select_related()、.values());
⚠️ 注意:性能随列表长度线性下降,仅建议用于 ≤ 100 项的场景;若存在重复 passport_number,all=True 可保留所有匹配项。

✅ 方案二:Python 层排序(简单灵活,牺牲 QuerySet 能力)

若对性能要求不高,或需进一步处理对象,可在内存中重排:

Django
Django

避免常见的 Django 错误——QuerySet 评估、N+1 查询、迁移冲突和 ORM 陷阱。

下载
lst = ['AA1111111', 'AD2222222', 'AA3333333', 'AA4444444', 'АВ5555555']
order_map = {passport: idx for idx, passport in enumerate(lst)}

users = list(User.objects.filter(passport_number__in=lst))
sorted_users = sorted(users, key=lambda u: order_map.get(u.passport_number, float('inf')))

✅ 优势:逻辑清晰、调试方便;
❌ 缺陷:返回的是普通 Python list,无法再调用 .filter()、.paginate() 等 QuerySet 方法,且全量加载到内存,大数据集易 OOM。

✅ 方案三(最佳实践):数据库 CASE WHEN 排序(高效 & 可链式)

利用 Django 的 Case + When 表达式,在 SQL 层实现精准排序,兼顾性能与 QuerySet 完整性:

from django.db.models import Case, When, IntegerField

lst = ['AA1111111', 'AD2222222', 'AA3333333', 'AA4444444', 'АВ5555555']

# 构建 CASE WHEN 排序规则
ordering = Case(
    *[When(passport_number=p, then=i) for i, p in enumerate(lst)],
    output_field=IntegerField()
)

queryset = User.objects.filter(passport_number__in=lst).order_by(ordering)

生成的 SQL(PostgreSQL 示例):

SELECT * FROM user
WHERE passport_number IN ('AA1111111', 'AD2222222', ...)
ORDER BY CASE
    WHEN passport_number = 'AA1111111' THEN 0
    WHEN passport_number = 'AD2222222' THEN 1
    -- ...
END

✅ 优势:一次查询、数据库原生排序、完全保留 QuerySet 功能(支持分页、注解、关联查询等);
? 提示:output_field=IntegerField() 是关键,避免类型推断错误;MySQL/SQLite 同样兼容。

⚠️ 重要注意事项

  • 模型命名规范:Django 官方反模式指南明确建议使用单数类名(如 User),而非 Users,以保持一致性;
  • 空值与缺失项:若列表中某些 passport_number 在库中不存在,CASE WHEN 和 union() 均会自动跳过;若需补 None 占位,需额外逻辑处理;
  • 性能基准:对于千级以上列表,优先测试 CASE WHEN 的执行计划;必要时可为 passport_number 字段添加索引。

综上,Case/When + order_by() 是最平衡的解决方案——它既尊重数据库能力,又无缝融入 Django ORM 生态,应作为首选实践。

相关文章

PHP速学视频免费教程(入门到精通)
PHP速学视频免费教程(入门到精通)

PHP怎么学习?PHP怎么入门?PHP在哪学?PHP怎么学才快?不用担心,这里为大家提供了PHP速学教程(入门到精通),有需要的小伙伴保存下载就能学习啦!

下载

相关标签:

django

本站声明:本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系admin@php.cn

相关专题

更多
python打包成可执行文件
python打包成可执行文件

本专题为大家带来python打包成可执行文件相关的文章,大家可以免费的下载体验。

2023.07.20

1671

4

python能做什么
python能做什么

python能做的有:可用于开发基于控制台的应用程序、多媒体部分开发、用于开发基于Web的应用程序、使用python处理数据、系统编程等等。本专题为大家提供python相关的各种文章、以及下载和课程。

2023.07.25

4184

7

format在python中的用法
format在python中的用法

Python中的format是一种字符串格式化方法,用于将变量或值插入到字符串中的占位符位置。通过format方法,我们可以动态地构建字符串,使其包含不同值。php中文网给大家带来了相关的教程以及文章,欢迎大家前来阅读学习。

2023.07.31

1669

3

python教程
python教程

Python已成为一门网红语言,即使是在非编程开发者当中,也掀起了一股学习的热潮。本专题为大家带来python教程的相关文章,大家可以免费体验学习。

2023.08.03

24277

23

python环境变量的配置
python环境变量的配置

Python是一种流行的编程语言,被广泛用于软件开发、数据分析和科学计算等领域。在安装Python之后,我们需要配置环境变量,以便在任何位置都能够访问Python的可执行文件。php中文网给大家带来了相关的教程以及文章,欢迎大家前来学习阅读。

2023.08.04

2967

5

python eval
python eval

eval函数是Python中一个非常强大的函数,它可以将字符串作为Python代码进行执行,实现动态编程的效果。然而,由于其潜在的安全风险和性能问题,需要谨慎使用。php中文网给大家带来了相关的教程以及文章,欢迎大家前来学习阅读。

2023.08.04

3007

5

scratch和python区别
scratch和python区别

scratch和python的区别:1、scratch是一种专为初学者设计的图形化编程语言,python是一种文本编程语言;2、scratch使用的是基于积木的编程语法,python采用更加传统的文本编程语法等等。本专题为大家提供scratch和python相关的文章、下载、课程内容,供大家免费下载体验。

2023.08.11

1163

5

python合并两个列表
python合并两个列表

Python是一种强大的编程语言,具有许多方便的功能和工具。在Python中,有多种方法可以合并两个列表。php中文网给大家带来了相关的教程以及文章,欢迎大家前来学习阅读。

2023.08.10

596

4

python是前端还是后端
python是前端还是后端

Python属于前端也属于后端,其灵活性和丰富的生态系统使得开发人员能够在不同的领域中灵活运用。本专题为大家提供python相关的文章、下载、课程内容,供大家免费下载体验。

2023.08.11

2323

5

热门下载

更多
网站特效
/
网站源码
/
网站素材
/
前端模板

精品课程

更多
相关推荐
/
热门推荐
/
最新课程
Django 6.1 官方文档
Django 6.1 官方文档

共0课时 | 0人学习

Django 教程
Django 教程

共28课时 | 9.8万人学习

Django DRF 源码解析
Django DRF 源码解析

共21课时 | 2万人学习