Django带Through中间表的多对多字段如何按创建时间倒序排序
问题原因
你之前写的排序规则没生效,核心是两个问题:
- 你在
Section模型里定义的get_section_info()方法从来没被调用过,模板里遍历的是object.section_infos.all,这个默认查询集不会套用你在自定义方法里写的排序逻辑 - 中间表
SectionInfo的Meta类里配置的ordering = ('info__date_created',)是创建时间正序(最早创建的条目在前),和你要的倒序需求完全相反,而且这个配置仅对直接查询SectionInfo表生效,不会作用于跨多对多关系取Info对象的查询。
可行修复方案
你可以根据自己的代码习惯选任意一种:
方案1:最小改动,模板直接调用已写好的排序方法
你已经在模型里写好了返回倒序结果的方法,Django模板调用无参方法不需要加括号,直接把模板里的遍历目标替换即可:
将原模板中这行:
{% for info in object.section_infos.all %}
替换为:
{% for info in object.get_section_info %}
改完刷新页面就能看到排序生效。
方案2:视图层预取排序(生产环境推荐,性能最好)
当前写法遍历每个Section再查关联Info会产生N+1数据库查询问题,在视图里用prefetch_related自定义关联查询的排序,既能实现排序需求,还能把查询次数降到2次,性能提升明显:
修改视图代码为:
from django.db.models import Prefetch def view_sections(request): object_list = Section.objects.prefetch_related( Prefetch( 'section_infos', queryset=Info.objects.order_by('-date_created') ) ).order_by('-date_created') context = { 'object_list':object_list, } return render(request, 'manufacturing/view_sections.html', context)
这个方案不需要修改模板代码,原模板里的object.section_infos.all遍历出来的直接就是按创建时间倒序的结果。
不要用JS在前端反转列表,后端排序更稳定,也不会出现页面加载时先显示正序再翻转的闪烁问题。
内容的提问来源于stack exchange,提问作者Alec
相关产品推荐
相关产品推荐

