如何在同一个模板中使用两个不同的 Django Form?

Posted

技术标签:

【中文标题】如何在同一个模板中使用两个不同的 Django Form?【英文标题】:How to use two different Django Form at the same template? 【发布时间】:2012-07-01 09:20:21 【问题描述】:

我的forms.py:

class AlertForm(forms.ModelForm):
class Meta:
    model=Alert
    fields = ('high','medium', 'user')
    widgets = 
        'user':  forms.HiddenInput()
    

AlertCountFormset = modelformset_factory(Alert,
                                       form = AlertForm)

另一个 Django 表单类:

class NotifierForm(forms.ModelForm):
high = forms.ChoiceField(choices=NOTIFIER_TYPE)
medium = forms.ChoiceField(choices=NOTIFIER_TYPE)
low = forms.ChoiceField(choices=NOTIFIER_TYPE)  

def save(self, commit=True):
    alert = super(NotifierForm, self).save(commit=False)
    alert.high = self.cleaned_data["high"]
    alert.medium = self.cleaned_data["medium"]
    alert.low = self.cleaned_data["low"]
    alert.save()
    return alert

class Meta:
    model=Notifier
    fields = ('high','medium', 'low', 'user')
    widgets = 
        'user': forms.HiddenInput()
    

NotifierFormset = modelformset_factory(Notifier,
                                    form = NotifierForm)

以下是选择字段:

NOTIFIER_TYPE = (
(0, _('E-mail')),
(1, _('Skype')),
(2, _('IRC'))
)

我想在同一个模板中填写这两个表格。所以我选择为两者写相同的视图,即:

def profile_setting(request, slug):
if request.method == 'POST':
    alert_form = AlertForm(request.POST)
    notifier_form = NotifierForm(request.POST)
    if alert_form.is_valid() and notifier_form.is_valid():
        alert = alert_form.save(commit=False)
        notifier = notifier_form.save(commit=False) 
        alert.user = request.user.username
        notifier.user = request.user.username
        notifier.save()
        alert.save()
        return HttpResponseRedirect(reverse('profile_setting', args=[slug]))

extra_context = 
    'alert_form': AlertForm(),
    'notifier_form': NotifierForm()

return direct_to_template(request,'users/user_profile_setting.html',
                          extra_context)

根据我的template.html:

% block content %
<h3>% trans "Alerts limit" %</h3>
<form action="" method="POST">% csrf_token %
     alert_form.as_p 
    <input type="submit" value="% trans 'Update' %" />
</form>

<h3>% trans "Notifier setting" %</h3>
<form action="" method="POST">% csrf_token %
     notifier_form.as_p 
    <input type="submit" value="% trans 'Update' %" />
</form>

一切都是正确的,它也将数据保存到数据库中。但问题是每当我填写aler_form 并单击更新按钮时。它还使用相同的值更新另一个表单,反之亦然。例如,如果我选择

1 2 3 for high , medium and low for alert_Form

然后它也会为 notify_form 保存相同的值。为什么会这样。是不是观点有问题?

【问题讨论】:

【参考方案1】:

问题在于您的表单上的字段具有相同的名称。

request.POST 是一个类似字典的对象。所以它只包含请求中的名称/值对。如果两个表单上的字段名称相同,那么当您调用

alert_form = AlertForm(request.POST)
notifier_form = NotifierForm(request.POST)

它们被初始化为相同的值。要解决此问题,请使名称在您的两个表单之间是唯一的。例如,在 AlertForm 上的所有字段名称前加上“alert_”。

【讨论】:

对不起,我没有得到你。哪两个名字? 感谢您的回答:) 还有一件事。每当我要更新表单中的所有字段时,这在 Django-Form 中是否可行。所有字段都应显示数据库中先前保存的值。 是的,有可能。包含两个表单实例的 extra_context。他们现在这样做的方式是传递未初始化的表单。如果要显示需要初始化的数据。【参考方案2】:

使用prefix 参数,这样您的字段名称就不会发生冲突。

例如:

alert form = AlertForm(request.POST, prefix='alert') 
notifier_form = NotifierForm(request.POST, prefix='notifier')

您需要在未绑定的表单中使用相同的前缀。

extra_context =  'alert_form': AlertForm(prefix='alert'),  notifier_form': NotifierForm(prefix='notifier') 

使用前缀的优点是您不需要手动重命名字段,正如 umnik700 在他们的回答中所建议的那样。

【讨论】:

除此之外的变化。我应该对模板端进行更改吗? 不,您不需要对模板进行任何更改。 添加后。什么都没有发生。我的意思是,没有值进入数据库。即使没有错误 您需要在未绑定表单(在extra_context 创建)中使用与绑定到帖子数据的表单相同的前缀。

以上是关于如何在同一个模板中使用两个不同的 Django Form?的主要内容,如果未能解决你的问题,请参考以下文章

Django Admin:为两个管理站点使用不同的模板

Django 在模板中使用两个不同的数据集填充表

Django 在一个模板中使用两个 FilterView 类

如何在列表 django 模板列表中使用变量

如何在 Django 模板中嵌套或联合使用两个模板标签?

如何在 django 模板中的另一个字段中更改后禁用复选框?