Django Crispy Forms: Применяйте пользовательский атрибут заголовка к каждой ошибке

Ситуация

Чтобы внести ошибки в форму регистрации, я делаю некоторые проверки в чистых методах класса формы (например, clean_email() и т.д.) и вызываю form.add_error('attribute', 'error message'). Я отображаю свои формы с помощью django-crispy-forms, используя тег шаблона {% crisy form %}.

Я хочу установить пользовательские атрибуты заголовка для сообщений об ошибках, которые отображаются в тегах span. Я бы предпочел иметь возможность сделать это в самой форме Django, если это возможно, но если есть другой способ, я открыт и для него.

Пример

Например, вместо...

<span id="error_1_id_password" class="invalid-feedback"><strong>Password must have an uppercase and a lowercase letter</strong></span>

<span title="Ошибка пароля 1" id="error_1_id_password" class="invalid-feedback"><strong>Password must have an uppercase and a lowercase letter</strong></span>

Я просмотрел некоторую документацию по FormHelper, но я не вижу никакого механизма, который позволил бы мне применять определенные title атрибуты к каждому сообщению об ошибке.

Текущая HTML-форма

HTML, который отображается для формы (обратите внимание, в частности, на теги span с ошибками):

Снимок экрана формы

Форма Django

class EmailAuthUserCreationForm(forms.Form):
first_name = forms.CharField(
    label='First name',
    required=True,
    widget=forms.TextInput(attrs={
        'placeholder': 'Your first name..',
    })
)

last_name = forms.CharField(
    label='Last name',
    required=True,
    widget=forms.TextInput(attrs={
        'placeholder': 'Your last name..',
    })
)

email = forms.EmailField(
    label='School email',
    required=True,
    widget=forms.TextInput(attrs={
        'placeholder': 'Your college/university email address..',
    })
)

password = forms.CharField(
    label='Create password',
    required=True,
    help_text='Must be 8-100 characters including an uppercase and lowercase character and a digit',
    widget=forms.PasswordInput(attrs={
        'placeholder': 'Enter password..',
    })
)

password_confirm = forms.CharField(
    label='Re-enter password',
    required=True,
    widget=forms.PasswordInput(attrs={
        'placeholder': 'Repeat the password..'
    })
)

role_choice = forms.CharField(
    label='Choose role',
    required=True,
    widget=forms.Select(choices=APP_ROLES)
)

tos = forms.BooleanField(
    label='Terms of Service',
    required=True,
)

def clean_email(self):
    if EmailAuthUser.objects.filter(email=self.cleaned_data['email'].lower()).exists():
        self.add_error('email', 'An account with this email address already exists.')

def clean_password_confirm(self):
    passwd1 = self.cleaned_data['password']
    passwd2 = self.cleaned_data['password_confirm']

    if passwd1 and passwd2:
        # Check that passwords match
        if passwd1 != passwd2:
            self.add_error('password_confirm', 'The passwords do not match.')

        # Check password requirements
        if len(passwd1) < 8:
            self.add_error('password', "Password must be 8-100 characters")
        if not schema1.validate(passwd1):
            self.add_error('password', "Password must have an uppercase and a lowercase letter")
        if not schema2.validate(passwd1):
            self.add_error('password' "Password must contain a digit and no spaces")

def __init__(self, *args, **kwargs):
    super().__init__(*args, **kwargs)
    self.helper = FormHelper()
    self.helper.form_class='form-horizontal'
    self.helper.label_class='col-25 fs-400 ff-sans-normal'
    self.helper.field_class='col-75'
    self.helper.form_tag = False
    self.helper.layout = Layout(
        Row(
            Column('first_name')
        ),
        Row(
            Column('last_name')
        ),
        Row(
            Column('email')
        ),
        Row(
            Column('password')
        ),
        Row(
            Column('password_confirm')
        ),
        Row(
            Column('role_choice')
        )
    )
Вернуться на верх