Django utilisant get_user_model vs settings.AUTH_USER_MODEL

96

Lecture de la documentation Django:

get_user_model ()

Au lieu de faire référence directement à User, vous devez référencer le modèle utilisateur en utilisant django.contrib.auth.get_user_model (). Cette méthode renverra le modèle User actuellement actif - le modèle User personnalisé si celui-ci est spécifié, ou User sinon.

Lorsque vous définissez une clé étrangère ou des relations plusieurs-à-plusieurs avec le modèle User, vous devez spécifier le modèle personnalisé à l'aide du paramètre AUTH_USER_MODEL.

Je suis confus avec le texte ci-dessus. Dois-je faire ceci:

author = models.ForeignKey(settings.AUTH_USER_MODEL)

ou ca...

author = models.ForeignKey(get_user_model())

Les deux semblent fonctionner.

Prométhée
la source

Réponses:

85

L'utilisation settings.AUTH_USER_MODELretardera la récupération de la classe de modèle réelle jusqu'à ce que toutes les applications soient chargées. get_user_modeltentera de récupérer la classe de modèle au moment où votre application est importée pour la première fois.

get_user_modelne peut pas garantir que le Usermodèle est déjà chargé dans le cache de l'application. Cela peut fonctionner dans votre configuration spécifique, mais il s'agit d'un scénario aléatoire. Si vous modifiez certains paramètres (par exemple l'ordre de INSTALLED_APPS), cela pourrait très bien interrompre l'importation et vous devrez passer plus de temps à déboguer.

settings.AUTH_USER_MODEL transmettra une chaîne comme modèle de clé étrangère, et si la récupération de la classe de modèle échoue au moment où cette clé étrangère est importée, la récupération sera retardée jusqu'à ce que toutes les classes de modèle soient chargées dans le cache.

knbk
la source
7
Concrètement, vous pouvez rencontrer des problèmes d'importation circulaire avec les modèles.ForeignKey (get_user_model ())
Chris Clark
2
Cette section de la documentation dit "De manière générale, vous devez référencer le modèle User avec le AUTH_USER_MODELparamètre dans le code qui est exécuté au moment de l'importation. Fonctionne get_user_model()uniquement une fois que Django a importé tous les modèles."
Hamish Downer
7
Donc concrètement, dans les fonctions (vues, méthodes modèle / sérialiseur / formulaire), utilisation get_user_model(), pour l'utilisation des attributs de classe AUTH_USER_MODEL?
Nick T
51

Nouveau depuis Django 1.11.

Depuis Django 1.11, vous pouvez utiliser get_user_model()dans les deux cas! Donc, si vous ne voulez pas vous en préoccuper davantage, allez-y.

"dans les deux cas" signifie: si vous avez besoin du modèle utilisateur pour accéder à ses attributs, ainsi que si vous voulez définir une relation ForeignKey / ManyToMany.

Depuis le journal des modifications :

get_user_model () peut maintenant être appelé au moment de l'importation, même dans les modules qui définissent des modèles.

alors ... y a-t-il encore une raison d'utiliser settings.AUTH_USER_MODEL? Eh bien, la documentation recommande toujours le settings.AUTH_USER_MODEL(qui est une chaîne) pour définir les relations, mais sans donner de raison explicite. Cela peut être bénéfique pour les performances, mais ne semble pas avoir beaucoup d'importance.

Exemple de code:

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
la source
Merci d'avoir signalé que cela get_user_model()peut être appelé au moment de l'importation; cependant, Django conseille toujours aux utilisateurs de définir les relations de clé étrangère et plusieurs-à-plusieurs en utilisant AUTH_USER_MODEL
kevins
2
merci d'avoir signalé cette recommandation, je l'ai en quelque sorte négligée lors de la rédaction de la réponse, mais maintenant je l'ai trouvée. J'ai essayé d'intégrer cela dans la réponse (toujours en faveur get_user_model, en particulier pour les lecteurs qui sont confus au sujet de la distinction)
Ilja
7

Depuis Django 1.11, get_user_model()utilise en fait 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
la source
-11

Un moyen de revenir au modèle utilisateur par défaut si AUTH_USER_MODEL n'est pas défini:

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

USER_MODEL = getattr(settings, 'AUTH_USER_MODEL', User)
synchroniser
la source
7
AUTH_USER_MODELa déjà une valeur par défaut, elle sera donc toujours définie.
knbk
4
settings.AUTH_USER_MODEL est également une chaîne et votre solution de remplacement Userest un modèle
Matt