Django中如何从模板调用表单方法实现动态表单?
问题分析与解决方案
核心问题
- 模板无法调用表单方法:Django Admin的
change_form.html模板中,表单实例需通过adminform.form访问,而非直接form变量,原代码中form.get_schemas无法找到对应实例。 - 字段渲染方式错误:直接输出字段对象不会生成HTML输入框,需通过表单的字段引用渲染完整的表单控件(含标签、输入框)。
- 动态字段分组逻辑缺失:原
get_schemas返回单个字段,未按Schema条目分组,不符合UI展示需求。
步骤1:修正表单方法与初始化逻辑
修改forms.py,完善Schema处理、新增索引获取方法,并添加表单提交后的字段值整合逻辑:
import json from django import forms from .models import MailTemplate, SCHEMA_DATA_TYPES class MailTemplateForm(forms.ModelForm): class Meta: model = MailTemplate fields = ['name', 'tfile', 'schema'] def __init__(self, *args, **kwargs): super().__init__(*args, **kwargs) # 处理Schema为空的情况 schema_data = self.instance.schema if schema_data: schema = json.loads(schema_data.strip()) for i in range(len(schema)): # 添加name字段(只读) self.fields[f'schema_{i}_name'] = forms.CharField( max_length=20, initial=schema[i]['name'], label=f"字段名称 {i+1}" ) self.fields[f'schema_{i}_name'].widget.attrs["readonly"] = True # 添加label字段 self.fields[f'schema_{i}_label'] = forms.CharField( max_length=20, required=True, initial=schema[i]['label'], label=f"显示标签 {i+1}" ) # 添加type字段 self.fields[f'schema_{i}_type'] = forms.ChoiceField( choices=SCHEMA_DATA_TYPES, initial=schema[i]['type'], label=f"数据类型 {i+1}" ) # 添加format字段 self.fields[f'schema_{i}_format'] = forms.CharField( max_length=20, required=True, initial=schema[i]['format'], label=f"格式 {i+1}" ) def get_schema_indices(self): """返回Schema条目的索引范围,用于模板循环""" schema_data = self.instance.schema if schema_data: return range(len(json.loads(schema_data.strip()))) return [] def clean(self): """收集动态字段值,更新回Schema字段""" cleaned_data = super().clean() schema = [] for i in self.get_schema_indices(): schema.append({ 'name': cleaned_data.get(f'schema_{i}_name'), 'label': cleaned_data.get(f'schema_{i}_label'), 'type': int(cleaned_data.get(f'schema_{i}_type')), 'format': cleaned_data.get(f'schema_{i}_format') }) cleaned_data['schema'] = json.dumps(schema) return cleaned_data
步骤2:修正Admin模板的表单引用与字段渲染
修改mailtemplate_form.html,使用adminform.form访问表单实例,按Schema条目分组渲染字段:
{% extends "admin/change_form.html" %} {% block after_field_sets %} {% if not add %} <div id="schema_head" style="margin: 15px 0;"> <b>Schema 配置</b> </div> <div id="additional_fields"> {% for i in adminform.form.get_schema_indices %} <div style="margin-bottom: 10px; padding: 10px; border: 1px solid #eee;"> {% with name_field='schema_'|add:i|stringformat:"s"|add:'_name' %} <div style="display: inline-block; margin-right: 15px;"> {{ adminform.form[name_field].label_tag }} {{ adminform.form[name_field] }} </div> {% endwith %} {% with label_field='schema_'|add:i|stringformat:"s"|add:'_label' %} <div style="display: inline-block; margin-right: 15px;"> {{ adminform.form[label_field].label_tag }} {{ adminform.form[label_field] }} </div> {% endwith %} {% with type_field='schema_'|add:i|stringformat:"s"|add:'_type' %} <div style="display: inline-block; margin-right: 15px;"> {{ adminform.form[type_field].label_tag }} {{ adminform.form[type_field] }} </div> {% endwith %} {% with format_field='schema_'|add:i|stringformat:"s"|add:'_format' %} <div style="display: inline-block;"> {{ adminform.form[format_field].label_tag }} {{ adminform.form[format_field] }} </div> {% endwith %} </div> {% endfor %} </div> {% endif %} {% endblock %}
模板说明
- 使用
adminform.form访问自定义表单实例,确保能调用get_schema_indices方法。 - 通过
with标签拼接动态字段名,使用adminform.form[field_name]渲染完整的表单控件(标签+输入框)。 - 添加基础样式优化展示效果,可根据需求调整。
步骤3:验证与测试
- 重启Django服务,进入MailTemplate的编辑页面,确认Schema动态字段正常显示。
- 修改字段值后提交表单,检查数据库中
schema字段的JSON值是否同步更新。
内容的提问来源于stack exchange,提问作者Bino Oetomo
相关产品推荐
相关产品推荐

