Django如何排除已关联指定Schede的Gruppi数据填充ModelChoiceField
解决方案
核心筛选逻辑
你可以直接通过Django ORM的跨表关联查询,动态排除当前Schede实例已关联的Gruppi数据,无需手动提取ID列表:
# 排除所有已和当前scheda关联的Gruppi记录 group_to_add = Gruppi.objects.exclude(dati_gruppo__gruppi_scheda=scheda)
这里利用了你定义的related_name做跨表查询:dati_gruppo是Gruppi指向DatiGruppi的反向关联名,后面再接gruppi_scheda指向Schede实例,直接筛选出所有已关联的Gruppi并排除即可。
视图代码优化
另外注意不要直接修改表单的base_fields属性,base_fields是表单类的全局属性,修改后会影响所有该表单的实例,引发并发场景下的选项错乱问题。同时POST请求分支下也需要给表单设置相同的筛选后queryset,否则会触发表单字段的验证错误。
修改后的完整视图代码如下:
def creazione(request, nome): scheda = get_object_or_404(Schede, nome_scheda = nome) eserciziFormSet = formset_factory(EserciziForm, extra = 0) # 提前定义统一的筛选queryset,GET和POST分支复用 group_queryset = Gruppi.objects.exclude(dati_gruppo__gruppi_scheda=scheda) if request.method == "POST": gruppo_form = GruppiForm(request.POST, prefix = 'gruppo') # 给POST请求的表单也设置筛选后的queryset gruppo_form.fields['dati_gruppo'].queryset = group_queryset if gruppo_form.is_valid(): gruppo = gruppo_form.save(commit = False) gruppo.gruppi_scheda = scheda gruppoName = gruppo_form.cleaned_data['dati_gruppo'] gruppo.save() esercizi_formset = eserciziFormSet(request.POST, prefix='esercizi') for esercizi in esercizi_formset: esercizi_instance = esercizi.save(commit = False) esercizi_instance.gruppo_single = get_object_or_404(DatiGruppi, gruppi_scheda = scheda.id, dati_gruppo = gruppoName) esercizi_instance.save() return HttpResponseRedirect(request.path_info) else: gruppo_form = GruppiForm(prefix = 'gruppo') # 实例化后修改单个表单实例的字段属性,不影响全局 gruppo_form.fields['dati_gruppo'].queryset = group_queryset esercizi_formset = eserciziFormSet(prefix='esercizi') context = {'scheda' : scheda, 'gruppo_form' : gruppo_form, 'esercizi_formset': esercizi_formset} return render(request, 'crea/passo2.html', context)
内容的提问来源于stack exchange,提问作者user15374373
相关产品推荐
相关产品推荐

