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']
:
Форма без novalidate - форма не может быть опубликована в случае ошибок:
шаблон
{% 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