Django forms.ValidationError не отображается в шаблоне и отправить не работает - PullRequest
0 голосов
/ 25 февраля 2019

В моем приложении Django у меня есть шаблон обратной связи с полями: название компании, контактный номер, адрес электронной почты.

Я определил def clean () для проверки адреса электронной почты и номера телефона следующим образом:

class ContactForm(forms.Form):
    def clean(self):
        super(ContactForm, self).clean()
        email_address = self.cleaned_data.get('email_address')
        contact_no = self.cleaned_data.get('contact_no')

        if validate_email(email_address):
            pattern = re.compile('^[2-9]\\d{9}$')
            if bool(pattern.match(contact_no)):
                return self.cleaned_data
            else: # error not displayed
                raise forms.ValidationError(
                    "Please enter a valid phone number")
        else: # error not displayed
            raise forms.ValidationError(
                "Please enter a valid email address")
        return self.cleaned_data

В шаблоне contact_us я также корректно отображаю ошибки:

<form method="post" action="{% url 'contact' %}">
    {% csrf_token %}
    {{contact_form.as_p}
    <input type="submit" value="Submit">
</form>

{% if contact_form.errors %}
    {% for field in contact_form %}
        {% for error in field.errors %}
        <div class="alert alert-danger">
            <strong>{{ error|escape }}</strong>
        </div>
        {% endfor %}
    {% endfor %}
{% endif %}

В views.py, даже если форма действительна и электронное письмоотправлено успешно, форма не отображается снова (как новая новая форма) в шаблоне.

 def contact(request):
     contact_form = ContactForm()

     if request.method == 'POST':
        contact_form = ContactForm(request.POST)
        if contact_form.is_valid():
            company_name = contact_form.cleaned_data.get('company_name')
            contact_no = contact_form.cleaned_data.get('contact_no')
            email_address = contact_form.cleaned_data.get('email_address')

            # send mail code

            contact_form.save()
            contact_form = ContactForm()
            return render(request, './mysite/contact_us.html', {
                'contact_form': contact_form, 'successful_submit': True})
     return render(request, './mysite/contact_us.html', {
         'contact_form': contact_form,
     })

1 Ответ

0 голосов
/ 25 февраля 2019

Вы повышаете ValidationError с clean(), поэтому ошибка хранится в form.non_field_errors - , который вы не отображаете , поэтому вы, очевидно, не можете видеть их действительно.

документированное решение вместо этого должно использовать self.add_error(<fieldname>, <msg>),

НО:

, но я выполняю проверку на двух полях, следовательноя использовал общий метод clean () вместо двух отдельных методов clean_field ().

form.clean() предназначен для проверки cross - проверки двух полей, которые зависят друг от друга.В вашем примере нет абсолютно никакой зависимости между обоими полями, вам не нужно значение адреса электронной почты для проверки номера телефона, и вам не нужен номер телефона для проверки адреса электронной почты.Итак, вы должны ДЕЙСТВИТЕЛЬНО использовать разные clean_field методы.

Обратите внимание, что даже если у вас была перекрестная проверка, вы все равно можете (и должны) использовать clean_field методы для того, что может быть проверено отдельно.В вашем случае у вас должен быть метод validate_email_address для проверки самой электронной почты (или просто используйте form.EmailField FWIW), а в clean() просто проверьте, была ли проверена электронная почта (если нет, вы найдете ошибку вself._errors['email_address']) раньше.

И пока мы на этом, у вашего кода есть немало других проблем.Здесь:

    if validate_email(email_address):
        pattern = re.compile('^[2-9]\\d{9}$')
        if bool(pattern.match(contact_no)):
            return self.cleaned_data
        else: # error not displayed
            raise forms.ValidationError(
                "Please enter a valid phone number")
    else: # error not displayed
        raise forms.ValidationError(
            "Please enter a valid email address")
    return self.cleaned_data

1 / предварительная компиляция регулярного выражения таким способом совершенно бесполезна.Либо вы прекомпилируете его на верхнем уровне модуля, чтобы он был скомпилирован только один раз (по крайней мере, для каждого процесса), либо вы вообще не компилируете его и вместо этого используете функции re, то есть if re.match(r"your expression here", your_variable) - модуль re будет не толькоскомпилируйте выражение, но также кэшируйте его для последующего повторного использования.

2 / if bool(pattern.match(contact_no)) -> вызов bool избыточен, Python все равно сделает это.

3 / но DjangoУ вас уже есть валидатор регулярных выражений, так что это то, что вы должны использовать.

4 / поток управления бесполезно сложен, и последний оператор возврата фактически никогда не будет выполнен.Это:

    if validate_email(email_address):
        pattern = re.compile('^[2-9]\\d{9}$')
        if bool(pattern.match(contact_no)):
            return self.cleaned_data
        else: # error not displayed
            raise forms.ValidationError(
                "Please enter a valid phone number")
    else: # error not displayed
        raise forms.ValidationError(
            "Please enter a valid email address")

будет намного более читабельным при раннем выходе:

    if not validate_email(email_address):
        raise forms.ValidationError(
            "Please enter a valid email address"
            )

    pattern = re.compile('^[2-9]\\d{9}$')
    if not pattern.match(contact_no)):
        raise forms.ValidationError(
            "Please enter a valid phone number"
            )

    return self.cleaned_data

5 /, но это все равно неправильно, так как проверка остановится на первомобнаруженная ошибка - вы хотите перехватить как можно больше ошибок проверки за один раз, чтобы пользователю не приходилось читать сообщение об ошибке, исправить одно поле, повторно отправить, найти другую ошибку , которая могла быть обнаружена,в первый раз , исправить это, повторно отправить и т. д. Ну, если, конечно, ваша цель не состоит в том, чтобы сделать это настолько сложным для пользователя, что он, конечно, перестанет пытаться использовать ваш сайт.

6 / yourВид кода тоже вдвойне неверен.Во-первых, вы должны сохранить форму (я полагаю, ModelForm) ПЕРЕД отправкой почты, чтобы вы не потеряли данные, если что-то пойдет не так, а затем, как уже упоминал Даниэль, вы должны всегда перенаправлять послеуспешное сообщение ( прочитайте это почему)

...