Django-модификация UserCreationForm

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

Я импортирую UserCreationForm в файл forms.py следующим образом:

from django.contrib.auth.forms import UserCreationForm

А затем я попытался изменить его следующим образом: Поля и все остальное полностью функционирует, только сообщения все еще по умолчанию, а не те, которые я пытался установить.

class UserSignUpForm(UserCreationForm):
    username = forms.CharField(label="custom",
                               error_messages={'required': 'custom.',
                                               'unique': 'custom.'})
    password1 = forms.CharField(label="custom", widget=forms.PasswordInput,
                                error_messages={'required': 'custom.'})
    password2 = forms.CharField(label="Potvrďte custom", widget=forms.PasswordInput,
                                error_messages={'required': 'custom.',
                                                'password_mismatch': 'custom.'})

    class Meta(UserCreationForm.Meta):
        model = User
        fields = UserCreationForm.Meta.fields
        error_messages = {
            'password_mismatch': {"password_mismatch": "custom"},
            'password_too_short': {"password_too_short": "custom"},
            'password_common': {"password_common": "custom"},
            'password_entirely_numeric': {"password_entirely_numeric": "custom"},
        }

Если кто-то знает, как решить эту проблему, пожалуйста, дайте мне знать. Я буду признателен за любые отзывы.

Для того чтобы вы могли перезаписать сообщение об ошибке с помощью атрибута Meta или поля формы error_messages, ValidationError должен быть передан через ModelForm._update_errors. Этого не происходит для ошибок, возникающих при проверке пароля - они добавляются напрямую, без дополнительных действий:

class BaseUserCreationForm(forms.ModelForm):

    def _post_clean(self):
        super()._post_clean()
        # Validate the password after self.instance is updated with form data
        # by super().
        password = self.cleaned_data.get("password2")
        if password:
            try:
                password_validation.validate_password(password, self.instance)
            except ValidationError as error:
                self.add_error("password2", error)

Переписать _post_clean

Одним из вариантов может быть перезапись метода _post_clean для вызова _update_errors вместо add_error:

class UserSignUpForm(UserCreationForm):
    ...

    class Meta(UserCreationForm.Meta): 
        ...
        error_messages = {
            NON_FIELD_ERRORS: {
                'password_mismatch': "custom mismatch",
                'password_too_short': "custom too short",
                'password_common': "custom common",
                'password_entirely_numeric': "custom numeric",
                "password_too_similar": "custom similar",
            }
        }

    def _post_clean(self):
        # Skip BaseUserCreationForm._post_clean:
        super(forms.ModelForm, self)._post_clean()
        # Validate the password after self.instance is updated with form data
        # by super().
        password = self.cleaned_data.get("password2")
        if password:
            try:
                password_validation.validate_password(password, self.instance)
            except ValidationError as error:
                # Re-instantiate the ValidationError with an error_dict.
                # Without this, the messages that _update_errors iterates
                # over are strings (as returned by ValidationError.__iter__) 
                # instead of ValidationError instances. But we need 
                # ValidationError instances to know which error code to look for.
                _error = ValidationError({NON_FIELD_ERRORS: error.error_list})
                self._update_errors(_error)

Заменить сообщения об ошибках

В качестве альтернативы можно просмотреть form._errors после завершения проверки и заменить сообщения об ошибках вручную:

    password2 = forms.CharField(
        label="Potvrďte custom",
        widget=forms.PasswordInput,
        error_messages={
            "required": "custom.",
            "password_too_similar": "foo",
            "password_too_short": "bar",
        },
    )

    def _post_clean(self):
        super()._post_clean()
        for field, error_list in self._errors.items():
            if (
                field == NON_FIELD_ERRORS
                and self._meta.error_messages
                and NON_FIELD_ERRORS in self._meta.error_messages
            ):
                error_messages = self._meta.error_messages[NON_FIELD_ERRORS]
            elif field in self.fields:
                error_messages = self.fields[field].error_messages
            else:
                continue
            for error in error_list.as_data():
                if error.code in error_messages:
                    error.message = error_messages[error.code]

Обратите внимание, что ошибки проверки пароля добавляются в поле "password2" - поэтому вам нужно объявить свои собственные сообщения об ошибках, используя атрибут error_message этого поля.


Второй вариант не пропускает BaseUserCreationForm._post_clean, поэтому в конечном итоге он, вероятно, является более чистым решением.

Вернуться на верх