Переопределить 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: Как, возможно, лучшая идея, почему бы не попытаться запросить профиль, который является классом модели, над которым вы имеете полный контроль? Вы всегда можете извлечь пользовательский объект из профиля, так что…

Другие вопросы по тегам