2011-06-29 26 views
9

Jak używać niestandardowego menedżera dla klasy auth_user w django?Nadpisanie menedżera UserManager w django

W moim projekcie django używam auth_user i mam podstawową klasę profilu. Na każdej stronie mojej witryny używam niektórych danych użytkowników i profili, więc każde zapytanie użytkownika powinno dołączyć do profilu.

Chciałem użyć select_related w metodzie get_query_set() w menedżerze niestandardowym, ale nie mogę znaleźć żadnego właściwego sposobu zdefiniowania jednego lub zastąpić istniejącego UserManager. Jakieś pomysły?

Uwaga: Nie chcę zastępować modelu użytkownika. Albo, dokładniej, już przesadziłem w różnych modelach proxy. Chcę, aby ten niestandardowy menedżer był używany w każdym modelu proxy.

Odpowiedz

6

OK, w końcu znalazłem poprawną odpowiedź. Najczystszym sposobem jest użycie niestandardowego zaplecza uwierzytelniania.

# 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 
3

To jest dość brzydkie, ale prawdopodobnie możesz unieruchomić właściwość User objects, np. w middleware:

# 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 

Następnie zamienić linię w settings.py:

MIDDLEWARE_CLASSES = (
    # ... 
    'django.contrib.auth.middleware.AuthenticationMiddleware', 
    # ... 
) 

przez:

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

Note1: Ten kod jest czysto teoretyczna, nie testowane ani nie mam czasu.

Uwaga2: Nie mogłem polecić korzystania z tego rozwiązania z punktu widzenia długoterminowej konserwacji.

Uwaga 3: Jeśli ktoś zasugeruje coś innego, prawdopodobnie powinien słuchać go bardziej niż mnie.

Uwaga4: Być może lepszym pomysłem jest zapytanie o profil, który jest klasą modelu, na której masz całkowitą kontrolę? Zawsze możesz pobrać obiekt użytkownika z profilu, więc ...

+0

Ponieważ nie mogę znaleźć żadnego czystszego sposobu, przyjmuję tę odpowiedź. Jednak wypełniłem raport o błędzie w django BT. Poczekaj i zobacz. https://code.djangoproject.com/ticket/16379 –

+3

Powinieneś naprawdę nie przyjąć tej odpowiedzi, ponieważ początkujący mogą stwierdzić, że jest to akceptowalne podejście do rozwiązania problemu, który podnosisz, podczas gdy nie jest. – NiKo

+0

Próbowałem i nie działało to niestety ... Byłoby prostym rozwiązaniem dla mnie – James

Powiązane problemy