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

如何在Django Model Admin中减少关联模型的重复查询次数

解决方案

核心优化思路是复用同个Model1实例对应的最新Model2查询结果,避免同个实例重复查询多次:

方案1:实例属性缓存(总查询次数10次,完全符合要求)

将查询最新Model2的逻辑抽为独立方法,把结果缓存到当前Model1实例的私有属性上,4个字段方法复用该缓存结果,单页10条数据只会产生10次查询。
修改后的Admin代码如下:

@admin.register(Model1)
class Model1Admin(admin.ModelAdmin):
    list_per_page = 10
    list_display = ['some_model1_fields', 'get_field1','get_field2', 'get_field3', 'get_field4']

    # 私有方法:缓存同个Model1对应的最新Model2实例
    def _get_latest_model2(self, obj):
        if not hasattr(obj, '_cached_latest_model2'):
            obj._cached_latest_model2 = obj.model2_set.last()
        return obj._cached_latest_model2

    def get_field1(self, obj):
        latest_model2 = self._get_latest_model2(obj)
        return latest_model2.field1 if latest_model2 else None

    def get_field2(self, obj):
        latest_model2 = self._get_latest_model2(obj)
        return latest_model2.field2 if latest_model2 else None

    def get_field3(self, obj):
        latest_model2 = self._get_latest_model2(obj)
        return latest_model2.field3 if latest_model2 else None

    def get_field4(self, obj):
        latest_model2 = self._get_latest_model2(obj)
        return latest_model2.field4 if latest_model2 else None

代码同时增加了空值兼容逻辑,避免部分Model1无关联Model2时触发属性不存在报错。

方案2:Prefetch批量预取(总查询次数仅2次,无JOIN关联性能问题)

如果你可以接受额外一次批量查询,可使用Django的prefetch_related进一步优化,该方案是做两次独立的单表查询,不会触发你担心的JOIN关联Count耗时问题:

from django.db import models

@admin.register(Model1)
class Model1Admin(admin.ModelAdmin):
    list_per_page = 10
    list_display = ['some_model1_fields', 'get_field1','get_field2', 'get_field3', 'get_field4']

    def get_queryset(self, request):
        qs = super().get_queryset(request)
        # 预取每个Model1对应的最新Model2,仅一次额外查询
        return qs.prefetch_related(
            models.Prefetch(
                'model2_set',
                # 排序逻辑和原last()保持一致即可,这里默认按主键倒序
                queryset=Model2.objects.order_by('-pk'),
                to_attr='_prefetched_latest_model2'
            )
        )

    def _get_latest_model2(self, obj):
        if not hasattr(obj, '_cached_latest_model2'):
            obj._cached_latest_model2 = obj._prefetched_latest_model2[0] if obj._prefetched_latest_model2 else None
        return obj._cached_latest_model2

    # 后续get_field1~get_field4方法和方案1完全一致,此处省略重复代码

内容的提问来源于stack exchange,提问作者Md Shahbaz Ahmad

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.10.02 14:30:03