Переопределить UserManager в Django
Как я могу использовать собственный менеджер для auth_user
класс в джанго?
В моем проекте Django я использую auth_user
и у меня есть базовый профиль класса. На каждой странице моего сайта я использую некоторые данные пользователя и профиля, поэтому каждый пользовательский запрос должен присоединяться к профилю.
Я хотел использовать select_related
в get_query_set()
метод в пользовательском менеджере, но я не могу найти какой-либо правильный способ определить один или переопределить существующий UserManager
, Есть идеи?
Примечание: я не хочу переопределять пользовательскую модель. Или, если быть более точным, я уже переопределил это в разных моделях прокси. Я хочу, чтобы этот пользовательский менеджер использовался в каждой модели прокси.
2 ответа
Хорошо, наконец-то нашел правильный ответ. Самый простой способ - использовать пользовательский бэкэнд аутентификации.
# in settings:
AUTHENTICATION_BACKENDS = ('accounts.backends.AuthenticationBackend',)
# in accounts/backends.py:
from django.contrib.auth.backends import ModelBackend
from django.contrib.auth.models import User
class AuthenticationBackend(ModelBackend):
def get_user(self, user_id):
try:
# This is where the magic happens
return User.objects. \
select_related('profile'). \
get(pk=user_id)
except User.DoesNotExist:
return None
Это довольно некрасиво, но вы можете, вероятно, monkeypatch пользователя objects
собственность, например в промежуточном программном обеспечении:
# manager.py
from django.contrib.auth.models import UserManager
class MyUserManager(UserManager):
def get_query_set(self):
qs = super(MyUserManager, self).get_query_set()
return qs.select_related('profile')
# middleware.py
from django.contrib.auth.middleware import AuthenticationMiddleware
from managers import MyUserManager
class MyAuthMiddleware(AuthenticationMiddleware):
def process_request(self, request):
super(AuthenticationMiddleware, self).process_request(request)
User.objects = MyUserManager()
return None
Затем замените строку в settings.py
:
MIDDLEWARE_CLASSES = (
# ...
'django.contrib.auth.middleware.AuthenticationMiddleware',
# ...
)
От:
# settings.py
MIDDLEWARE_CLASSES = (
# ...
'yourapp.middleware.MyAuthMiddleware',
# ...
)
Примечание 1: Этот код является чисто теоретическим, никогда не тестировался, и у меня нет времени на это.
Примечание 2: я не мог бы рекомендовать использовать это решение с точки зрения долгосрочного обслуживания.
Примечание 3: Если кто-то предлагает что-то еще, вы, вероятно, должны слушать его или ее больше, чем я.
Примечание 4: Как, возможно, лучшая идея, почему бы не попытаться запросить профиль, который является классом модели, над которым вы имеете полный контроль? Вы всегда можете извлечь пользовательский объект из профиля, так что…