Django używając get_user_model vs settings.AUTH_USER_MODEL

98

Czytanie dokumentacji Django:

get_user_model ()

Zamiast odwoływać się bezpośrednio do użytkownika, należy odwołać się do modelu użytkownika za pomocą django.contrib.auth.get_user_model (). Ta metoda zwróci aktualnie aktywny model użytkownika - niestandardowy model użytkownika, jeśli został określony, lub użytkownik w innym przypadku.

Podczas definiowania klucza obcego lub relacji wiele-do-wielu z modelem użytkownika, należy określić model niestandardowy za pomocą ustawienia AUTH_USER_MODEL.

Jestem zdezorientowany z powyższym tekstem. Powinienem to zrobić:

author = models.ForeignKey(settings.AUTH_USER_MODEL)

albo to...

author = models.ForeignKey(get_user_model())

Obie wydają się działać.

Prometeusz
źródło

Odpowiedzi:

87

Użycie settings.AUTH_USER_MODELopóźni pobieranie rzeczywistej klasy modelu do momentu załadowania wszystkich aplikacji. get_user_modelspróbuje pobrać klasę modelu w momencie pierwszego zaimportowania aplikacji.

get_user_modelnie może zagwarantować, że Usermodel jest już załadowany do pamięci podręcznej aplikacji. Może działać w twojej konkretnej konfiguracji, ale jest to scenariusz chybiony. Jeśli zmienisz niektóre ustawienia (np. Kolejność INSTALLED_APPS), może to bardzo dobrze przerwać import i będziesz musiał poświęcić więcej czasu na debugowanie.

settings.AUTH_USER_MODEL przekaże ciąg jako model klucza obcego, a jeśli pobranie klasy modelu nie powiedzie się w momencie importowania tego klucza obcego, pobieranie zostanie opóźnione do momentu załadowania wszystkich klas modelu do pamięci podręcznej.

knbk
źródło
7
Konkretnie, możesz napotkać problemy z cyklicznym importem modeli.ForeignKey (get_user_model ())
Chris Clark
2
Ta sekcja dokumentacji mówi: „Ogólnie rzecz biorąc, powinieneś odwoływać się do modelu użytkownika z AUTH_USER_MODELustawieniami w kodzie, które są wykonywane w czasie importu. get_user_model()Działa tylko wtedy, gdy Django zaimportuje wszystkie modele”.
Hamish Downer
7
A więc konkretnie, w funkcjach (widokach, modelach / serializatorach / metodach formularzy) używać get_user_model()do używania atrybutów klas AUTH_USER_MODEL?
Nick T
53

Nowość od Django 1.11.

Od Django 1.11 możesz używać get_user_model()w obu przypadkach! Więc jeśli nie chcesz się tym bardziej przejmować, po prostu weź to.

„w obu przypadkach” oznacza: jeśli potrzebujesz modelu użytkownika, aby uzyskać dostęp do jego atrybutów, a także jeśli chcesz zdefiniować relację ForeignKey / ManyToMany.

Z dziennika zmian :

Funkcja get_user_model () może być teraz wywoływana w czasie importu, nawet w modułach definiujących modele.

więc ... czy nadal jest powód do używania settings.AUTH_USER_MODEL? Cóż, dokumentacja nadal zaleca settings.AUTH_USER_MODEL(który jest ciągiem znaków) do definiowania relacji, ale bez podawania wyraźnego powodu. Może być korzystny dla wydajności, ale nie wydaje się mieć większego znaczenia.

Przykład kodu:

from django.db import models
from django.contrib.auth import get_user_model
...
    ...
    user = models.ForeignKey(
        get_user_model(),
        null=True, # explicitly set null, since it's required in django 2.x. - otherwise migrations will be incompatible later!
        ...
    )
Ilja
źródło
Dziękujemy za wskazanie, że get_user_model()można zadzwonić w czasie importu; jednak Django nadal radzi, aby użytkownicy definiowali relacje klucza obcego i wiele do wielu za pomocą AUTH_USER_MODEL
kevins
2
dziękuję za wskazanie tej rekomendacji, jakoś przeoczyłem ją pisząc odpowiedź, ale teraz ją znalazłem. Próbowałem uwzględnić to w odpowiedzi (nadal faworyzuję get_user_model, szczególnie dla czytelników, którzy są zdezorientowani co do tego rozróżnienia)
Ilja
7

Od Django 1.11 get_user_model()faktycznie używa settings.AUTH_USER_MODEL:

def get_user_model():
    """
    Return the User model that is active in this project.
    """
    try:
        return django_apps.get_model(settings.AUTH_USER_MODEL, require_ready=False)
    except ValueError:
        raise ImproperlyConfigured("AUTH_USER_MODEL must be of the form 'app_label.model_name'")
    except LookupError:
        raise ImproperlyConfigured(
            "AUTH_USER_MODEL refers to model '%s' that has not been installed" % settings.AUTH_USER_MODEL
        )
Murey Tasroc
źródło
0

settings.AUTH_USER_MODEL zwraca ciąg (lokalizację modelu użytkownika), np. „user_accounts.User”

get_user_model () zwraca ACTUAL klasę modelu, a nie ciąg.

Więc w przypadkach, gdy potrzebujesz modelu User, użyj get_user_model (). Jeśli potrzebujesz jego lokalizacji (module.model jako ciąg znaków), użyj ustawień.AUTH_USER_MODEL.

ImportError
źródło
-11

Sposób na powrót do domyślnego modelu użytkownika, jeśli AUTH_USER_MODEL nie jest ustawiony:

from django.conf import settings
from django.contrib.auth.models import User

USER_MODEL = getattr(settings, 'AUTH_USER_MODEL', User)
synw
źródło
7
AUTH_USER_MODELma już wartość domyślną, więc zawsze będzie ustawiona.
knbk
4
settings.AUTH_USER_MODEL to także ciąg znaków, a Twoim zastępczym Usermodelem jest model
Matt