HTML5允许某些表单元素的“浏览器端”验证;例如对于<input type="number">
,如果您输入的不是数字,则会弹出一个小气泡。
通过在表单标签上添加novalidate
属性或在“提交”按钮上添加formnovalidate
属性,可以抑制发送表单之前的验证,从而使服务器负责所有验证。
默认情况下,django使用novalidate
,因为它的形式错误更容易被看到。
但是这里有个问题:使用novalidate
时,可以验证客户端并且具有无效数据的任何 表单元素的数据,都将被忽略在到达服务器的请求中。服务器不再能够验证这些错误元素的数据,结果,输入错误数据的用户将永远不会意识到自己的错误。
forms.py
class WorstFormEver(Form):
a = IntegerField(required = False) # use the default NumberInput widget, allowing HTML5 validation
b = IntegerField(required = False, widget = TextInput) # TextInput does not include HTML5 validation
采用此表格,并在两个字段中都填写字母。
views.py
class WorstViewEver(FormView):
form_class = WorstFormEver
template_name = 'admin/worst.html'
success_url = reverse_lazy('worst')
novalidate = True
def get_context_data(self, **kwargs):
context = super().get_context_data(**kwargs)
context['novalidate'] = self.novalidate
return context
def post(self, request, *args, **kwargs):
print(self.request.POST.get('a','PANIC!')) # prints [''] if self.novalidate is True
return super().post(request, *args, **kwargs)
人们希望该视图返回带有两个字段均具有错误的表单的响应,但是当b
为空a字段的错误>!
a
的无效数据甚至从未发送到服务器。
带有novalidate的表单-request.POST
包含'a': [''], 'b': ['bar']
:
模板
{% extends 'admin/base_site.html' %}
{% block content %}
<form method="post" {% if novalidate %}novalidate{% endif %}>
{% csrf_token %}
{{ form }}
<input type="submit">
</form>
{% endblock content %}
删除novalidate
甚至都不会让您发送表单(如预期的那样)。
我也可以将所有可能支持HTML5验证的小部件替换为无聊的旧TextInput
小部件,但这感觉更像是对待症状而不是原因。
我宁愿不使用HTML5验证,因为某些形式可能非常大,而django的错误表示则更加清晰(而且内容丰富)。
我的问题是如何使用novalidate
(因为我想同时使用特定于字段的窗口小部件和仅django的验证)而不会丢失数据。问题是,尽管明确设置了novalidate
,某事仍在进行某种验证并删除数据。
使用: django v1.11,以上示例在Firefox上进行了测试