如果未选择任何选项,带有 ModelChoiceField(required=True) 的表单不会引发 ValidationError
Form with ModelChoiceField(required=True) doesn't raise ValidationError if no option is selected
我有一个表单,如果所有字段无效,都会引发 ValidationErrors。但是,如果没有从 ModelChoiceField 中选择任何选项,则表单都不会提交(这很好)并且 也不会在模板中引发任何 ValidationError。
如果提交时没有选择类别,似乎if request.method == 'POST':
returns False
。
# Form
class PollersForm(forms.Form):
# Poller Category
poller_category = forms.ModelChoiceField(widget=forms.RadioSelect(attrs={
'class': 'poller-category-radio',
}), queryset=Category.objects.all().order_by('category'), label='Select a Category', required=True)
# View
def raise_poller(request):
"""
creates a new Poller object according to user inputs and redirects to it
"""
# if this is a POST request we need to process the form data
if request.method == 'POST':
# create a form instance and populate it with data from the request:
form = PollersForm(request.POST)
# check whether it's valid:
if form.is_valid():
# process the remaining data in form.cleaned_data as required
poller_category = form.cleaned_data['poller_category']
# Get the user
created_by = request.user
# Save the poller to the database
p = Poller(
poller_category=poller_category,
)
p.save()
# Get the created object and its id to redirect to the single poller view
created_poller = Poller.objects.get(created_by=created_by, id=p.pk)
created_poller_id = created_poller.pk
created_poller_slug = created_poller.slug
poller_url = '/poller/' + str(created_poller_id) + '/' + str(created_poller_slug)
# redirect to a new URL:
return redirect(poller_url, request, created_poller_id)
# if a GET (or any other method) we'll create a blank form
else:
form = PollersForm()
return render(request, 'pollinator/raise_poller.html', {'form': form})
<!-- Template -->
<form action="/raisepoller/" method="post">
{% csrf_token %}
{{ form.non_field_errors }}
{{ form.errors }}
<!-- Poller Categories -->
<div class="fieldWrapper">
<div class="label">{{ form.poller_category.label_tag }}</div>
<div class="category-ctn">
{% for category in form.poller_category %}
<div class="category-wrapper">{{ category }}</div>
{% endfor %}
</div>
</div>
<!-- Submit Button -->
<button type="submit" value="Publish Poller" id="raise-poller-button">
<div class="button-wrapper">
<div class="button-icon"><img id="button-image" src="{% static 'images/send.png' %}"></div>
<div class="button-text">Publish Poller</div>
</div>
</button>
</form>
...呈现:
<div class="category-wrapper"><label for="id_poller_category_1"><input type="radio" name="poller_category" value="5" class="poller-category-radio" id="id_poller_category_1" required="">
Environment</label></div>
/* CSS */
.category-wrapper input {
position: fixed;
visibility: hidden;
}
.category-wrapper label {
display: inline-block;
background-color: #fdfdfd;
color: var(--main-darkblue-color);
padding: 0.2vw 0.5vw;
font-size: 1vw;
border: 2px solid #444;
border-radius: 4px;
margin-bottom: 0;
}
必填=真
只检查字段中是否有东西
通过这个
您可以检查响应数据以了解该字段是否有任何默认值吗?
It seems that if request.method == 'POST':
returns False
if no category is selected on submit.
浏览器甚至没有发送请求,因为 HTML5 验证失败。
由于 input
上的 visibility: hidden
,未显示验证消息。
.category-wrapper input {
position: fixed;
visibility: hidden;
}
...这会导致您的浏览器控制台中显示此错误:
❗An invalid form control with name='category' is not focusable.
改为透明、无宽度和无边距:
.category-wrapper input {
margin: 0;
opacity: 0;
width: 0;
}
发生这种情况是因为视图通过了第一个 if
if request.method == 'POST':
创建表格
# create a form instance and populate it with data from the request:
form = PollersForm(request.POST)
然后检查它是否有效
# check whether it's valid:
if form.is_valid():
因为它无效,所以视图返回到第一个缩进并使用内部错误的表单呈现模板。
else:
form = PollersForm()
return render(request, 'pollinator/raise_poller.html', {'form': form})
你能做的最好的事情就是从 else
中取出 request.method 的干净形式
form = PollersForm()
return render(request, 'pollinator/raise_poller.html', {'form': form})
我有一个表单,如果所有字段无效,都会引发 ValidationErrors。但是,如果没有从 ModelChoiceField 中选择任何选项,则表单都不会提交(这很好)并且 也不会在模板中引发任何 ValidationError。
如果提交时没有选择类别,似乎if request.method == 'POST':
returns False
。
# Form
class PollersForm(forms.Form):
# Poller Category
poller_category = forms.ModelChoiceField(widget=forms.RadioSelect(attrs={
'class': 'poller-category-radio',
}), queryset=Category.objects.all().order_by('category'), label='Select a Category', required=True)
# View
def raise_poller(request):
"""
creates a new Poller object according to user inputs and redirects to it
"""
# if this is a POST request we need to process the form data
if request.method == 'POST':
# create a form instance and populate it with data from the request:
form = PollersForm(request.POST)
# check whether it's valid:
if form.is_valid():
# process the remaining data in form.cleaned_data as required
poller_category = form.cleaned_data['poller_category']
# Get the user
created_by = request.user
# Save the poller to the database
p = Poller(
poller_category=poller_category,
)
p.save()
# Get the created object and its id to redirect to the single poller view
created_poller = Poller.objects.get(created_by=created_by, id=p.pk)
created_poller_id = created_poller.pk
created_poller_slug = created_poller.slug
poller_url = '/poller/' + str(created_poller_id) + '/' + str(created_poller_slug)
# redirect to a new URL:
return redirect(poller_url, request, created_poller_id)
# if a GET (or any other method) we'll create a blank form
else:
form = PollersForm()
return render(request, 'pollinator/raise_poller.html', {'form': form})
<!-- Template -->
<form action="/raisepoller/" method="post">
{% csrf_token %}
{{ form.non_field_errors }}
{{ form.errors }}
<!-- Poller Categories -->
<div class="fieldWrapper">
<div class="label">{{ form.poller_category.label_tag }}</div>
<div class="category-ctn">
{% for category in form.poller_category %}
<div class="category-wrapper">{{ category }}</div>
{% endfor %}
</div>
</div>
<!-- Submit Button -->
<button type="submit" value="Publish Poller" id="raise-poller-button">
<div class="button-wrapper">
<div class="button-icon"><img id="button-image" src="{% static 'images/send.png' %}"></div>
<div class="button-text">Publish Poller</div>
</div>
</button>
</form>
...呈现:
<div class="category-wrapper"><label for="id_poller_category_1"><input type="radio" name="poller_category" value="5" class="poller-category-radio" id="id_poller_category_1" required="">
Environment</label></div>
/* CSS */
.category-wrapper input {
position: fixed;
visibility: hidden;
}
.category-wrapper label {
display: inline-block;
background-color: #fdfdfd;
color: var(--main-darkblue-color);
padding: 0.2vw 0.5vw;
font-size: 1vw;
border: 2px solid #444;
border-radius: 4px;
margin-bottom: 0;
}
必填=真
只检查字段中是否有东西
通过这个
您可以检查响应数据以了解该字段是否有任何默认值吗?
It seems that
if request.method == 'POST':
returnsFalse
if no category is selected on submit.
浏览器甚至没有发送请求,因为 HTML5 验证失败。
由于 input
上的 visibility: hidden
,未显示验证消息。
.category-wrapper input {
position: fixed;
visibility: hidden;
}
...这会导致您的浏览器控制台中显示此错误:
❗An invalid form control with name='category' is not focusable.
改为透明、无宽度和无边距:
.category-wrapper input {
margin: 0;
opacity: 0;
width: 0;
}
发生这种情况是因为视图通过了第一个 if
if request.method == 'POST':
创建表格
# create a form instance and populate it with data from the request:
form = PollersForm(request.POST)
然后检查它是否有效
# check whether it's valid:
if form.is_valid():
因为它无效,所以视图返回到第一个缩进并使用内部错误的表单呈现模板。
else:
form = PollersForm()
return render(request, 'pollinator/raise_poller.html', {'form': form})
你能做的最好的事情就是从 else
中取出 request.method 的干净形式form = PollersForm()
return render(request, 'pollinator/raise_poller.html', {'form': form})