Задать вопрос
@Mikkkch

Логика авторизации в форме или в backend?

Здравствуйте, в моей кастомной модели в качестве поля username выступает email. Соответственно для того, чтобы пользователь мог благополучно войти нужно и переписать логику входа посредствам email.
Это можно сделать двумя способами, но каким будет правильнее?

1. Можно переписать AuthenticationForm из django.contrib.auth.forms следующим образом:
def clean(self):
        username = self.cleaned_data.get('username')
        password = self.cleaned_data.get('password')

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

        return self.cleaned_data

Так как внутри функции authenticate мы обращаемся к бэкенду, логика которого выглядит так:
def authenticate(self, request, username=None, password=None, **kwargs):
        if username is None:
            username = kwargs.get(UserModel.USERNAME_FIELD)
        if username is None or password is None:
            return
        try:
            user = UserModel._default_manager.get_by_natural_key(username)
        except UserModel.DoesNotExist:
            # Run the default password hasher once to reduce the timing
            # difference between an existing and a nonexistent user (#20760).
            UserModel().set_password(password)
        else:
            if user.check_password(password) and self.user_can_authenticate(user):
                return user

Здесь стоит внимание обратить на вторую строку. В ней из словаря именованных аргументов мы вытягиваем USERNAME_FIELD, значением которого как раз является строка 'email.'

2. Можно написать кастомный бэкенд, что я и сделал:
class ConsumerAuthenticationBackend(ModelBackend):
    def authenticate(self, request, username=None, password=None, **kwargs):
        kwargs['email'] = username
        return super().authenticate(request, password=password, **kwargs)

Здесь мы обращаемся к родительскому методу и делаем так, чтобы сбратала проверка на отсутствие имени пользователя и его метод попытался достать из kwargs, куда мы и засунули наш емейл.

Подскажите, пожалуйста, как правильнее поступить? Не нужно писать, что поступай так, как тебе удобно. Меня интересует best practice.
  • Вопрос задан
  • 51 просмотр
Подписаться 1 Простой Комментировать
Пригласить эксперта
Ваш ответ на вопрос

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

Похожие вопросы