如何优化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
相关产品推荐
相关产品推荐

