Создание кастомного бекенда для авторизации
В модуле system, в папке services, я создам файл backends.py
Напоминаю, что я использую декомпозицию в своем проекте и храню все по отдельности.
modules/system/services/backends.py
from django.contrib.auth.backends import ModelBackend, UserModel
from django.contrib.auth.models import User
from django.core.exceptions import MultipleObjectsReturned
from django.db.models import Q
class UserModelBackend(ModelBackend):
"""
Переопределение авторизации
"""
def authenticate(self, request, username=None, password=None, **kwargs):
try:
user = UserModel.objects.get(Q(username=username) | Q(email__iexact=username))
except UserModel.DoesNotExist:
UserModel().set_password(password)
except MultipleObjectsReturned:
return User.objects.filter(email=username).order_by('id').first()
else:
if user.check_password(password) and self.user_can_authenticate(user):
return user
def get_user(self, user_id):
try:
user = UserModel.objects.get(pk=user_id)
except UserModel.DoesNotExist:
return None
return user if self.user_can_authenticate(user) else None
Пояснение:
- Наследуемся от обычного класса ModelBackend, который уже предусмотрен системой Django.
- Переопределяем два метода: authenticate, get_user
- В
authenticate
делаем возможность авторизации по имени пользователя и по email с помощью Q. - В
get_user
получаем пользователя.
Добавим соответствующие настройки в settings.py
backend/settings.py
# Custom backends
AUTHENTICATION_BACKENDS = ['modules.system.services.backends.UserModelBackend']
Пояснение:
- Добавил почти в самый низ файла.
Смотрим результат на сайте:
Авторизуемся по email:


Отлично. Авторизуемся по логину:


Все работает так, как нам надо. Отлично.