Django表单M2M关联字段多选复选框已绑定值未勾选问题排查
问题根因
你遇到的问题和修改__str__方法没有关联,是表单初始化和传参的逻辑存在疏漏:
- 更新场景下没有给
groups字段设置初始值,导致已关联的分组不会默认勾选 - 新建事件场景下,表单初始化时没有传入所属公司参数,原
__init__中直接读取instance.company会触发属性不存在错误,影响分组列表加载 - 表单默认字段列表未包含
groups,表单保存时不会自动处理该字段的多对多关联关系
具体修改方案
1. 表单代码修改
class EventDetail(forms.ModelForm): groups = forms.ModelMultipleChoiceField( label = "Liste des groupes", queryset = None, widget = forms.CheckboxSelectMultiple, required = False ) class Meta: model = Event # 把groups加入表单字段列表 fields = ['event_name', 'event_date', 'quorum', 'rule', 'groups'] def __init__(self, *args, **kwargs): # 提取视图传入的公司参数,供新建场景使用 company = kwargs.pop('company', None) super().__init__(*args, **kwargs) instance = self.instance # 区分新建/更新场景获取所属公司 if instance.pk: current_company = instance.company # 设置已关联分组为默认勾选状态 self.fields['groups'].initial = instance.groups.all() else: current_company = company self.fields['groups'].queryset = UserGroup.objects.filter( company=current_company, hidden=False ).order_by('group_name')
2. 视图代码修改
@user_passes_test(lambda u: u.is_superuser or (u.id is not None and u.usercomp.is_admin)) def adm_event_detail(request, comp_slug, evt_id=0): company = Company.get_company(request.session['comp_slug']) if evt_id > 0: current_event = Event.objects.get(id=evt_id) event_form = EventDetail(request.POST or None, instance=current_event) else: # 新建场景传入公司参数 event_form = EventDetail(request.POST or None, company=company) if request.method == 'POST': if event_form.is_valid(): if evt_id == 0: new_event = event_form.save(commit=False) new_event.company = company # 原有生成slug的逻辑请自行补充到此处 new_event.save() # 保存多对多关联关系 event_form.save_m2m() else: new_event = event_form.save() else: print("****** FORMULAIRE NON VALIDE *******") print(event_form.errors) return render(request, "polls/adm_event_detail.html", locals())
如果你不想把
groups加入Meta.fields,也可以保留原有手动处理cleaned_data的逻辑,只需要在更新场景下手动设置groups的初始值、保存关联即可,不需要修改Meta.fields配置。
内容的提问来源于stack exchange,提问作者Christophe
相关产品推荐
相关产品推荐

