You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

Django Admin中非外键字段的每行数据库查询优化方案

解决Django Admin中非外键关联的N+1查询问题

核心思路

因为两个模型没有外键关联,没法直接用prefetch_related,所以我们可以批量预取所有需要的App数据,缓存到字典里,之后在自定义字段方法里直接从字典取值,避免每行重复查询。

具体实现

重写ModelAdmin的get_queryset方法,先收集当前页所有对象的app_no,一次性查询所有对应的App数据,然后用app_no作为键存到实例变量中:

class MyModelAdmin(admin.ModelAdmin):
    list_display = ('data_from_app_a', 'data_from_app_b', ...)

    def get_queryset(self, request):
        qs = super().get_queryset(request)
        # 收集当前页所有非空的app_no
        app_nos = [obj.app_no for obj in qs if obj.app_no]
        # 批量查询并构建app_no到App对象的映射字典
        self.app_data_map = {
            app.app_no: app for app in App.objects.filter(app_no__in=app_nos)
        }
        return qs

    def data_from_app_a(self, obj):
        # 从缓存字典取数据,处理无对应记录的情况
        app_obj = self.app_data_map.get(obj.app_no)
        return app_obj.field_a if app_obj else "-"

    def data_from_app_b(self, obj):
        app_obj = self.app_data_map.get(obj.app_no)
        return app_obj.field_b if app_obj else "-"

效果说明

原来的实现中,每一行数据会触发2次App模型查询,N行就是2N次数据库请求;修改后,不管当前页有多少行,只需要1次批量查询,能大幅减少数据库交互次数,提升列表页加载速度。

额外优化点

  • 过滤空的app_no,避免无效的数据库查询;
  • 如果需要处理超大量数据(远超Django Admin默认分页条数),可以考虑分批次预取,但常规分页场景下上述方案已经足够高效。

内容的提问来源于stack exchange,提问作者swaran

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.07.02 07:02:03