@3FANG

Как создать форму для ввода пароля?

Использую базовую CBV для удаления пользователя (django.views.generic.edit.DeleteView). По умолчанию он использует пустую форму, а я хочу чтобы пользователь вводил подтверждение удаления с помощью пароля, т.е. мне нужно определить собственную форму и присвоить ее переменной класса form_class.
Я попробовал сделать форму, ориентируясь на AuthenticationForm:

class DeleteUserForm(forms.Form):
    """Форма для удаления пользователя с подтвреждением при помощи пароля."""
    
    password = forms.CharField(
        label="Пароль",
        strip=False,
        widget=forms.PasswordInput(attrs={"autocomplete": "current-password"}),
    )

    def __init__(self, request=None, *args, **kwargs):
        """
        The 'request' parameter is set for custom auth use by subclasses.
        The form data comes in via the standard 'data' kwarg.
        """
        self.request = request
        self.user_cache = None
        super().__init__(*args, **kwargs)

    def clean(self):
        username = self.request.user.username
        password = self.cleaned_data.get("password")

        if username is not None and password:
            self.user_cache = authenticate(
                self.request, username=username, password=password
            )
            if self.user_cache is None:
                raise self.get_invalid_login_error()
            else:
                self.confirm_login_allowed(self.user_cache)

        return self.cleaned_data


Т.е. я скопировал clear заменив username = self.cleaned_data.get("username") на username = self.request.user.username. Т.е. я добавил только поле password для ввода, а username хотел брать из self.request. Но, как оказалось request в таком случае - None. Соответственно возникает ошибка AttributeError: 'NoneType' object has no attribute 'user'.

Сделал как в LoginView - переопределил get_form_kwargs()моей Вью:
class UserDeleteView(OwnerTestMixin, DeleteView):
    """Класс-представление для удаление отдельного пользователя."""

    model = User
    form_class = DeleteUserForm
    pk_url_kwarg = "user_id"
    success_url = reverse_lazy('all_users')
    template_name = "users/delete.html"
    error_message = "У вас нет прав для удаления другого пользователя."

    def get_form_kwargs(self):
        kwargs = super().get_form_kwargs()
        kwargs["request"] = self.request
        return kwargs


Также я скопировал методы get_invalid_login_error() (в которой изменил params={"username": self.username_field.verbose_name} на params={"username": self.request.user.username} и confirm_login_allowed()из AuthenticationForm. В итоге получилось это:

class DeleteUserForm(forms.Form):
    """Форма для удаления пользователя с подтврждением при помощи пароля."""
    
    password = forms.CharField(
        label="Пароль",
        strip=False,
        widget=forms.PasswordInput(attrs={"autocomplete": "current-password"}),
    )

    error_messages = {
        "invalid_login": 
            "Please enter a correct %(username)s and password. Note that both "
            "fields may be case-sensitive."
        ,
        "inactive": "This account is inactive.",
    }

    def __init__(self, request=None, *args, **kwargs):
        """
        The 'request' parameter is set for custom auth use by subclasses.
        The form data comes in via the standard 'data' kwarg.
        """
        self.request = request
        self.user_cache = None
        super().__init__(*args, **kwargs)

    def clean(self):
        username = self.request.user.username
        password = self.cleaned_data.get("password")

        if username is not None and password:
            self.user_cache = authenticate(
                self.request, username=username, password=password
            )
            if self.user_cache is None:
                raise self.get_invalid_login_error()
            else:
                self.confirm_login_allowed(self.user_cache)

        return self.cleaned_data
    
    def confirm_login_allowed(self, user):
        """
        Controls whether the given User may log in. This is a policy setting,
        independent of end-user authentication. This default behavior is to
        allow login by active users, and reject login by inactive users.

        If the given user cannot log in, this method should raise a
        ``ValidationError``.

        If the given user may log in, this method should return None.
        """
        if not user.is_active:
            raise ValidationError(
                self.error_messages["inactive"],
                code="inactive",
            )

    def get_invalid_login_error(self):
        return ValidationError(
            self.error_messages["invalid_login"],
            code="invalid_login",
            params={"username": self.request.user.username},
        )


И это вроде работает.
Но я более чем уверен, что это, мягко говоря, неправильно. Подскажите, как нужно было сделать?

Спасибо за потраченное на меня время.
  • Вопрос задан
  • 53 просмотра
Пригласить эксперта
Ваш ответ на вопрос

Войдите, чтобы написать ответ

Войти через центр авторизации
Похожие вопросы