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

Django关联模型表单显示时重复数据库查询问题优化咨询

解决Django表单下拉框重复查询问题

问题场景

使用CreateView结合关联FilesData模型的SendRnxForm表单时,表单中的el_type下拉框会重复执行查询ElType表的SQL语句,产生不必要的数据库请求。

相关代码

模型定义

class ElType(models.Model):
    name = models.CharField(max_length=16, db_index=True, verbose_name="Types el")
    slug = models.SlugField(max_length=24, unique=True, db_index=True, verbose_name="Код")

    def __str__(self):
        return self.name

class FilesData(models.Model):
    el_type = models.ForeignKey(ElType, blank=False, default='1', on_delete=models.DO_NOTHING, related_name='files', verbose_name="Types el")

表单定义

class SendRnxForm(forms.ModelForm):
    class Meta:
        model = FilesData
        fields = ['el_type',]
        widgets = {
            'el_type': forms.Select(attrs={'class': 'form-select', 'id': 'elTypeId'}),
        }

视图定义

class dashForm(DataMixin, CreateView):
    form_class = SendRnxForm
    template_name = 'dashApp/dash.html'
    success_url = reverse_lazy('home')

解决方案

重复查询的根源是ModelForm默认会在每次访问字段的queryset时执行数据库查询,若表单被多次初始化(比如模板重复渲染、视图逻辑多次调用),就会触发重复请求。我们可以通过提前缓存ElType的查询结果来解决,当前场景无需使用select_related或prefetch_related(仅需获取ElType自身数据,无跨模型关联查询需求)。

方案1:重写表单的__init__方法

在表单初始化时一次性获取ElType数据并赋值给字段,确保仅执行一次查询:

class SendRnxForm(forms.ModelForm):
    class Meta:
        model = FilesData
        fields = ['el_type',]
        widgets = {
            'el_type': forms.Select(attrs={'class': 'form-select', 'id': 'elTypeId'}),
        }

    def __init__(self, *args, **kwargs):
        super().__init__(*args, **kwargs)
        # 一次性获取所有ElType记录并排序
        el_type_queryset = ElType.objects.all().order_by('id')
        self.fields['el_type'].queryset = el_type_queryset
        # 设置默认选中第一条记录(可选,根据需求调整)
        if el_type_queryset.exists():
            self.fields['el_type'].initial = el_type_queryset.first().id

方案2:在视图中重写get_form方法

在视图层提前获取ElType数据,传递给表单字段:

class dashForm(DataMixin, CreateView):
    form_class = SendRnxForm
    template_name = 'dashApp/dash.html'
    success_url = reverse_lazy('home')

    def get_form(self, form_class=None):
        form = super().get_form(form_class)
        # 预加载ElType数据
        el_type_queryset = ElType.objects.all().order_by('id')
        form.fields['el_type'].queryset = el_type_queryset
        # 设置默认选中第一条记录(可选)
        if el_type_queryset.exists():
            form.fields['el_type'].initial = el_type_queryset.first().id
        return form

说明

两种方案本质都是通过提前执行一次查询并复用结果,避免每次表单初始化时重复触发数据库请求。当前场景无需使用select_related或prefetch_related,因为我们仅需查询ElType模型本身,没有涉及跨模型的关联数据获取。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.06.29 07:08:14