一个视图中的多个 Django Crispy 表单
Multiple Django Crispy Forms In One View
当使用 form|crispy 过滤器在视图中放置 2 个表单时,此答案在单个视图中处理 2 个表单:Proper way to handle multiple forms on one page in Django I am getting this 错误。
views.py:
def test_form(request):
if not request.user.is_authenticated():
return redirect(settings.LOGIN_URL)
title = 'test form'
row_control_form = RowControlForm(request.POST or None)
entry_form = EntryForm(request.POST or None)
context = {
'title': title,
'row_control_form': row_control_form,
'entry_form': entry_form,
}
if 'row_control_submit' in request.POST:
if row_control_form.is_valid():
row_control_form.save()
if 'entry_submit' in request.POST:
if entry_form.is_valid():
entry_form.save()
return render(request, "timesheet/test_form.html", context)
forms.py
class RowControlForm(forms.ModelForm):
class Meta:
model = RowControl
fields = ['month_control_record', 'department', 'activity', 'notes']
def clean(self):
cleaned_data = self.cleaned_data
# Ensures row is unique
try:
RowControl.objects.get(month_control_record=cleaned_data['month_control_record'],
department=cleaned_data['department'],
activity=cleaned_data['activity'],
notes=cleaned_data['notes'])
except RowControl.DoesNotExist:
pass
else:
raise ValidationError('This row already exists')
# Always return cleaned data
return cleaned_data
class EntryForm(forms.ModelForm):
class Meta:
model = Entry
fields = ['row_control', 'date', 'hours']
def clean(self):
cleaned_data = self.cleaned_data
# Ensures data is unique (only 1 hours entry for each date and row_control)
try:
Entry.objects.get(row_control=cleaned_data['row_control'],
date=cleaned_data['date'])
except Entry.DoesNotExist:
pass
else:
raise ValidationError('This entry already exists')
# Always return cleaned data
return cleaned_data
test_form.html
{% extends "base.html" %}
{% load crispy_forms_tags %}
{% block content %}
<div class="col-md-6 col-md-offset-3">
<h1 class="page-header"> Form Test </h1>
<form method="POST" action="{{ request.path }}">
{% csrf_token %}
{{ row_control_form|crispy }}
<button class="btn btn-primary" type="submit" value="Submit" name="row_control_submit" ><i class="fa fa-lg fa-floppy-o"></i> Save</button> </form>
</br>
</div>
<div class="col-md-6 col-md-offset-3">
<h1 class="page-header"> Form Test </h1>
<form method="POST" action="{{ request.path }}">
{% csrf_token %}
{{ entry_form|crispy }}
<button class="btn btn-primary" type="submit" value="Submit" name="entry_submit" ><i class="fa fa-lg fa-floppy-o"></i> Save</button> </form>
</br>
</div>
{% endblock %}
为错误提供上下文:
forms.py 的第 42 行是:
Entry.objects.get(row_control=cleaned_data['row_control'],
编辑:进一步的调查表明,无论按下哪个提交按钮,两个表单验证都是 运行,为 RowControlForm 提交有效数据时的 request.POST 是:
<QueryDict: {'csrfmiddlewaretoken': ['HffmmbI31Oe0tItYDfYC4MoULQHL0KvF'], 'notes': ['Cool'], 'row_control_submit': ['Submit'], 'month_control_record': ['1'], 'department': ['1'], 'activity': ['1']}>
因此 entry_submit 不在 request.POST 中并且验证不应该 运行 但它是?
首先,您需要修复表单 clean
方法的这一行
def clean(self):
...
Entry.objects.get(row_control=cleaned_data['row_control'],
您不能假设 row_control
会出现在 cleaned_data
中。您需要添加检查 if 'row_control' in cleaned_data
或捕获 KeyError
,然后适当更新方法的其余部分。您应该修复此问题,即使您在将多个表单放在一页上之前没有看到此错误。在 POST 请求中遗漏一个值应该不可能导致 500 服务器错误。即使页面上只有一个表单,用户也可以这样做。
两种形式的验证都是 运行,因为无论按下哪个提交按钮,您都使用 post 数据实例化两种形式。
row_control_form = RowControlForm(request.POST or None)
entry_form = EntryForm(request.POST or None)
您只应将 POST 数据用于您要提交的表单。
row_control_form = RowControlForm()
entry_form = EntryForm()
if 'row_control_submit' in request.POST:
row_control_form = RowControlForm(request.POST)
if row_control_form.is_valid():
if 'entry_submit' in request.POST:
entry_form = EntryForm(request.POST)
if entry_form.is_valid():
entry_form.save()
最后,最好在用户成功提交有效表单后重定向用户。
当使用 form|crispy 过滤器在视图中放置 2 个表单时,此答案在单个视图中处理 2 个表单:Proper way to handle multiple forms on one page in Django I am getting this 错误。
views.py:
def test_form(request):
if not request.user.is_authenticated():
return redirect(settings.LOGIN_URL)
title = 'test form'
row_control_form = RowControlForm(request.POST or None)
entry_form = EntryForm(request.POST or None)
context = {
'title': title,
'row_control_form': row_control_form,
'entry_form': entry_form,
}
if 'row_control_submit' in request.POST:
if row_control_form.is_valid():
row_control_form.save()
if 'entry_submit' in request.POST:
if entry_form.is_valid():
entry_form.save()
return render(request, "timesheet/test_form.html", context)
forms.py
class RowControlForm(forms.ModelForm):
class Meta:
model = RowControl
fields = ['month_control_record', 'department', 'activity', 'notes']
def clean(self):
cleaned_data = self.cleaned_data
# Ensures row is unique
try:
RowControl.objects.get(month_control_record=cleaned_data['month_control_record'],
department=cleaned_data['department'],
activity=cleaned_data['activity'],
notes=cleaned_data['notes'])
except RowControl.DoesNotExist:
pass
else:
raise ValidationError('This row already exists')
# Always return cleaned data
return cleaned_data
class EntryForm(forms.ModelForm):
class Meta:
model = Entry
fields = ['row_control', 'date', 'hours']
def clean(self):
cleaned_data = self.cleaned_data
# Ensures data is unique (only 1 hours entry for each date and row_control)
try:
Entry.objects.get(row_control=cleaned_data['row_control'],
date=cleaned_data['date'])
except Entry.DoesNotExist:
pass
else:
raise ValidationError('This entry already exists')
# Always return cleaned data
return cleaned_data
test_form.html
{% extends "base.html" %}
{% load crispy_forms_tags %}
{% block content %}
<div class="col-md-6 col-md-offset-3">
<h1 class="page-header"> Form Test </h1>
<form method="POST" action="{{ request.path }}">
{% csrf_token %}
{{ row_control_form|crispy }}
<button class="btn btn-primary" type="submit" value="Submit" name="row_control_submit" ><i class="fa fa-lg fa-floppy-o"></i> Save</button> </form>
</br>
</div>
<div class="col-md-6 col-md-offset-3">
<h1 class="page-header"> Form Test </h1>
<form method="POST" action="{{ request.path }}">
{% csrf_token %}
{{ entry_form|crispy }}
<button class="btn btn-primary" type="submit" value="Submit" name="entry_submit" ><i class="fa fa-lg fa-floppy-o"></i> Save</button> </form>
</br>
</div>
{% endblock %}
为错误提供上下文: forms.py 的第 42 行是:
Entry.objects.get(row_control=cleaned_data['row_control'],
编辑:进一步的调查表明,无论按下哪个提交按钮,两个表单验证都是 运行,为 RowControlForm 提交有效数据时的 request.POST 是:
<QueryDict: {'csrfmiddlewaretoken': ['HffmmbI31Oe0tItYDfYC4MoULQHL0KvF'], 'notes': ['Cool'], 'row_control_submit': ['Submit'], 'month_control_record': ['1'], 'department': ['1'], 'activity': ['1']}>
因此 entry_submit 不在 request.POST 中并且验证不应该 运行 但它是?
首先,您需要修复表单 clean
方法的这一行
def clean(self):
...
Entry.objects.get(row_control=cleaned_data['row_control'],
您不能假设 row_control
会出现在 cleaned_data
中。您需要添加检查 if 'row_control' in cleaned_data
或捕获 KeyError
,然后适当更新方法的其余部分。您应该修复此问题,即使您在将多个表单放在一页上之前没有看到此错误。在 POST 请求中遗漏一个值应该不可能导致 500 服务器错误。即使页面上只有一个表单,用户也可以这样做。
两种形式的验证都是 运行,因为无论按下哪个提交按钮,您都使用 post 数据实例化两种形式。
row_control_form = RowControlForm(request.POST or None)
entry_form = EntryForm(request.POST or None)
您只应将 POST 数据用于您要提交的表单。
row_control_form = RowControlForm()
entry_form = EntryForm()
if 'row_control_submit' in request.POST:
row_control_form = RowControlForm(request.POST)
if row_control_form.is_valid():
if 'entry_submit' in request.POST:
entry_form = EntryForm(request.POST)
if entry_form.is_valid():
entry_form.save()
最后,最好在用户成功提交有效表单后重定向用户。