在 Django 表单中传递自定义表单值到视图

在Django中,我们可以通过表单的初始化参数initial来传递自定义的初始值给表单字段。如果我们想要在视图中设置表单的初始值,可以在视图中创建表单的实例时,传递一个字典给initial参数。

1、问题背景

我们遇到了这样一个问题:在使用 Django 表单时,我们希望将自定义表单中的值传递到视图中。然而,我们发现无法为多选选项的每个选项传递值。在渲染表单时,只有一个字符字段,而多选框中有多个选择。我们想知道是否有办法解决这个问题,以及表单集是否可以在这里提供帮助。我们对 Django 还很陌生,因此希望得到一些解释,以便更好地理解和学习。

python 复制代码
# 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、解决方案

方法一:生成所需数量的字段

一种解决方案是编写一个循环来生成所需数量的字段。例如:

python 复制代码
# 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 对象。

python 复制代码
# 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)

使用表单集的好处是,我们可以轻松地处理多个对象,而且代码也更加简洁。

相关推荐
打鱼又晒网15 分钟前
【MySQL】数据库精细化讲解:内置函数知识穿透与深度学习解析
数据库·mysql
大白要努力!20 分钟前
android 使用SQLiteOpenHelper 如何优化数据库的性能
android·数据库·oracle
运维-大白同学26 分钟前
将django+vue项目发布部署到服务器
服务器·vue.js·django
喜欢猪猪28 分钟前
Django:从入门到精通
后端·python·django
tatasix1 小时前
MySQL UPDATE语句执行链路解析
数据库·mysql
南城花随雪。1 小时前
硬盘(HDD)与固态硬盘(SSD)详细解读
数据库
儿时可乖了1 小时前
使用 Java 操作 SQLite 数据库
java·数据库·sqlite
懒是一种态度1 小时前
Golang 调用 mongodb 的函数
数据库·mongodb·golang
天海华兮1 小时前
mysql 去重 补全 取出重复 变量 函数 和存储过程
数据库·mysql
gma9992 小时前
Etcd 框架
数据库·etcd