Переопределить UserManager в django

как я могу использовать пользовательский менеджер для auth_user класс в Джанго?

в моем проекте django я использую auth_user и у меня есть базовый класс профиль. На каждой странице моего сайта, я использую некоторые данные пользователя и профиля, поэтому каждый запрос пользователя должен присоединиться профиля.

Я хотел использовать select_related на get_query_set() метод в пользовательском менеджере, но я не могу найти правильного способа определить его или переопределить существующий UserManager. Есть идеи?

примечание: Я не хочу переопределите модель пользователя. Или, если быть более точным, я уже преодолел его в разных прокси-моделях. Я хочу, чтобы этот пользовательский менеджер использовался в каждой прокси-модели.

2 ответов


Ok, наконец-то нашел правильный ответ. Самый чистый способ-использовать пользовательский сервер аутентификации.

# 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',
    # ...
)

By:

# settings.py
MIDDLEWARE_CLASSES = (
    # ...
    'yourapp.middleware.MyAuthMiddleware',
    # ...
)

Note1: этот код чисто теоретический, никогда не проверялся, и у меня нет времени.

Note2: я не мог бы рекомендовать использовать это решение с точки зрения долгосрочной ремонтопригодности.

Note3: если кто-то предложит что-то еще, вы наверное, стоит слушать его или ее больше, чем меня.

Note4: как, вероятно, лучшая идея, почему бы не попытаться запросить профиль, который является классом модели, который вы полностью контролируете? Вы всегда можете получить объект пользователя из профиля, так что...