如何修复django-forms-dynamic中对象与章节下拉菜单未关联问题
Django Forms Dynamic 三级联动修复方案
问题根源分析
你的表单中对象与章节未关联的核心原因有三个:
contractor_section字段未声明依赖contractor_object,导致django-forms-dynamic无法监听对象字段的变化来更新章节选项section_choices中直接使用字符串类型的对象ID进行过滤,与外键字段的类型不匹配initial_sections返回单个对象,不符合ModelMultipleChoiceField对初始值的可迭代要求
修复代码
1. 修改 forms.py
class WorkLogForm(DynamicFormMixin, forms.ModelForm): def object_choices(form): contractor_counter = form['contractor_counter'].value() object_query = ObjectList.objects.filter(contractor_guid__in=[contractor_counter]) return object_query def initial_object(form): contractor_counter = form['contractor_counter'].value() object_query = ObjectList.objects.filter(contractor_guid__in=[contractor_counter]) return object_query.first() def section_choices(form): contractor_object_id = form['contractor_object'].value() # 转成整数匹配外键ID类型,无值时返回空查询集 if contractor_object_id: section_query = SectionList.objects.filter(object_id=int(contractor_object_id)) return section_query return SectionList.objects.none() def initial_sections(form): contractor_object_id = form['contractor_object'].value() if contractor_object_id: section_obj = SectionList.objects.filter(object_id=int(contractor_object_id)).first() return [section_obj] if section_obj else [] # 返回列表适配多选字段 return [] contractor_counter = forms.ModelChoiceField( label='Контрагент', queryset=CounterParty.objects.all(), # 修正初始无选项问题 initial=CounterParty.objects.first(), empty_label='', ) contractor_object = DynamicField( forms.ModelChoiceField, label='Объект', queryset=object_choices, initial=initial_object, depends_on='contractor_counter', # 明确依赖交易对手字段 ) contractor_section = DynamicField( forms.ModelMultipleChoiceField, label='Раздел', queryset=section_choices, initial=initial_sections, depends_on='contractor_object', # 关键:添加对象字段依赖 widget=forms.SelectMultiple(), )
2. 确认 views.py 视图逻辑
确保contractor_section视图能正确接收对象参数:
def contractor_section(request): form = WorkLogForm(request.GET, user=request.user) return HttpResponse(form['contractor_section'])
3. 前端联动补充(示例)
确保对象字段变化时触发章节下拉框更新:
$('#id_contractor_object').change(function() { const objectId = $(this).val(); $.get('/your-url/contractor_section/', {contractor_object: objectId}, function(data) { $('#id_contractor_section').html(data); }); });
额外说明
- 修正了
contractor_counter初始无选项的问题,将queryset改为CounterParty.objects.all() - 给
section_choices添加空值判断,避免类型转换报错 - 调整
initial_sections返回格式,匹配多选字段对初始值的可迭代要求
内容的提问来源于stack exchange,提问作者Zesshi
相关产品推荐
相关产品推荐

