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

如何优化Django视图中迭代键-QuerySet字典导致的代码臃肿问题

Django 视图冗余优化方案

核心思路是将字段分组配置、非空值过滤逻辑从视图层下沉到模型层,配合模板标签实现多端复用,彻底消除视图中的冗余代码。

具体实现步骤

1. 模型层抽离字段配置与处理逻辑

在你的模型类中统一维护所有需要分组展示的字段配置,同时封装非空值查询方法,完全避免在视图中硬写字典和循环逻辑:

from django.db import models

class MyModel(models.Model):
    # 原有字段保持不变
    growth_temp_low = models.CharField(verbose_name="低温", max_length=30, null=True, blank=True)
    growth_temp_room = models.CharField(verbose_name="室温", max_length=30, null=True, blank=True)
    growth_temp_body = models.CharField(verbose_name="体温", max_length=30, null=True, blank=True)
    growth_temp_high = models.CharField(verbose_name="高温", max_length=30, null=True, blank=True)
    # 其他字段省略

    # 全局字段分组配置,新增分组只需要在这里加配置即可
    DISPLAY_FIELD_GROUPS = {
        "temperature": {
            "title": "Temperature tolerance",
            "fields": ["growth_temp_low", "growth_temp_room", "growth_temp_body", "growth_temp_high"],
            "template_filter": "growstemp"
        }
        # 后续新增pH值、耐盐性等分组直接在这里补充,无需修改视图和模板基础逻辑
    }

    def get_group_non_empty_values(self, group_name: str) -> list:
        """获取指定分组下所有非空的字段值列表"""
        group_config = self.DISPLAY_FIELD_GROUPS.get(group_name, {})
        fields = group_config.get("fields", [])
        # 用列表推导式替代手动循环append,代码更简洁
        return [getattr(self, field) for field in fields if getattr(self, field, None) not in (None, "")]

2. 视图层简化

视图中不再需要单独拼接每个分组的列表,直接传递模型实例即可:

from django.shortcuts import get_object_or_404, render

def bacteria_detail_view(request, slug):
    instance = get_object_or_404(MyModel, slug=slug)
    return render(request, "your_template_path.html", {"instance": instance})

3. 模板层逻辑优化

原有模板代码直接调整为调用模型封装好的方法即可,逻辑保持兼容:

<li>
    {% with temperature_list=instance.get_group_non_empty_values "temperature" %}
        {% if temperature_list %}
            <i style="color: blue"><b>T</b>emperature tolerance:</i>
            {% for t in temperature_list %}
                {{ t|growstemp|default_if_none:'' }}
            {% endfor %}
        {% endif %}
    {% endwith %}
</li>

如果存在多组同类展示需求,可以进一步封装为Django inclusion标签实现一行调用,彻底消除模板重复代码:

# 在你的自定义标签文件中新增
from django import template

register = template.Library()

@register.inclusion_tag("components/field_group_render.html")
def render_field_group(instance, group_name):
    group_config = instance.DISPLAY_FIELD_GROUPS.get(group_name, {})
    if not group_config:
        return {}
    return {
        "title": group_config.get("title"),
        "values": instance.get_group_non_empty_values(group_name),
        "filter": group_config.get("template_filter")
    }

新建components/field_group_render.html模板片段:

{% if values %}
<li>
    {% if title %}
    <i style="color: blue"><b>{{ title.0 }}</b>{{ title.1 }}</i>
    {% endif %}
    {% for val in values %}
        {% if filter %}
            {{ val|filter }}
        {% else %}
            {{ val }}
        {% endif %}
    {% endfor %}
</li>
{% endif %}

之后所有字段组的展示只需要在页面中写一行代码即可:

{% render_field_group instance "temperature" %}

额外拓展:获取字段verbose_name映射

如果需要同时输出字段的显示名和值,可以在模型中新增以下方法,直接调用Django内置的字段元数据能力,不需要手动维护键值对字典:

def get_group_fields_with_verbose(self, group_name: str) -> list[dict]:
    group_config = self.DISPLAY_FIELD_GROUPS.get(group_name, {})
    fields = group_config.get("fields", [])
    res = []
    for field_name in fields:
        val = getattr(self, field_name, None)
        if val not in (None, ""):
            res.append({
                "verbose_name": self._meta.get_field(field_name).verbose_name,
                "value": val
            })
    return res

优化优势

  • 所有字段相关的配置、处理逻辑集中在模型层,全局复用,修改时只需要调整一处,不会出现多端代码不同步的问题
  • 视图层没有冗余的列表拼接逻辑,后续新增字段分组无需修改视图代码
  • 模板层复用率高,新增同类展示需求仅需要补充模型配置,无需重复写判断、循环代码
  • 完全符合Django的MTV分层设计理念,逻辑职责更清晰

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.09.24 23:45:04