赞
踩
在Django中,我们可以通过表单的初始化参数initial
来传递自定义的初始值给表单字段。如果我们想要在视图中设置表单的初始值,可以在视图中创建表单的实例时,传递一个字典给initial
参数。
1、问题背景
我们遇到了这样一个问题:在使用 Django 表单时,我们希望将自定义表单中的值传递到视图中。然而,我们发现无法为多选选项的每个选项传递值。在渲染表单时,只有一个字符字段,而多选框中有多个选择。我们想知道是否有办法解决这个问题,以及表单集是否可以在这里提供帮助。我们对 Django 还很陌生,因此希望得到一些解释,以便更好地理解和学习。
# models.py class StateOption(models.Model): partstate = models.ForeignKey(State) partoption = models.ForeignKey(Option) relevantoutcome = models.ManyToManyField(Outcome, through='StateOptionOutcome') class StateOptionOutcome(models.Model): stateoption = models.ForeignKey(StateOption) relevantoutcome = models.ForeignKey(Outcome) outcomevalue = models.CharField(max_length=20) # forms.py class UpdateStateOptionWithOutcomesForm(forms.ModelForm): class Meta: model = StateOption exclude = ['partstate', 'partoption'] def __init__(self, *args, **kwargs): super(UpdateStateOptionWithOutcomesForm, self).__init__(*args, **kwargs) self.fields['relevantoutcome'] = forms.ModelMultipleChoiceField(queryset=Outcome.objects.all(), required=True, widget=forms.CheckboxSelectMultiple) self.fields['outcomevalue'] = forms.CharField(widget=forms.TextInput(attrs={'size': '30'})) # views.py stateoption = get_object_or_404(StateOption, pk=stateoption_id) if request.method == "POST": form = UpdateStateOptionWithOutcomesForm(request.POST, instance=stateoption) if form.is_valid(): cd = form.cleaned_data outcomevalue = cd['outcomevalue'] for outcome_id in request.POST.getlist('relevantoutcome'): stateoption_outcome = StateOptionOutcome.objects.create(stateoption=stateoption, relevantoutcome_id=int(outcome_id), outcomevalue=outcomevalue) # template.html {% for field in form %} {{ field.label }}: {{ field }} {% if field.errors %} {{ field.errors|striptags }} {% endif %} {% endfor %}
2、解决方案
方法一:生成所需数量的字段
一种解决方案是编写一个循环来生成所需数量的字段。例如:
# forms.py
# ...
outcome_qs = Outcome.objects.all()
self.fields['relevantoutcome'] = forms.ModelMultipleChoiceField(queryset=outcome_qs, required=True, widget=forms.CheckboxSelectMultiple)
for outcome in outcome_qs:
# Use Outcome primary key to easily match two fields in your view.
self.fields['outcomevalue_%s' % outcome.pk] = forms.CharField(widget=forms.TextInput(attrs={'size':'30'})
方法二:使用表单集
另一种解决方案是使用表单集。表单集允许我们创建一组类似的表单,每个表单都可以处理单个对象。在我们的例子中,我们可以创建一个表单集来处理每个 StateOptionOutcome
对象。
# forms.py class StateOptionOutcomeForm(forms.ModelForm): class Meta: model = StateOptionOutcome fields = ['relevantoutcome', 'outcomevalue'] StateOptionOutcomeFormSet = forms.formset_factory(StateOptionOutcomeForm, extra=1) # views.py stateoption = get_object_or_404(StateOption, pk=stateoption_id) if request.method == "POST": formset = StateOptionOutcomeFormSet(request.POST) if formset.is_valid(): for form in formset: stateoption_outcome = StateOptionOutcome.objects.create(stateoption=stateoption, **form.cleaned_data)
使用表单集的好处是,我们可以轻松地处理多个对象,而且代码也更加简洁。
Copyright © 2003-2013 www.wpsshop.cn 版权所有,并保留所有权利。