Django usando get_user_model vs settings.AUTH_USER_MODEL

96

Lendo a documentação do Django:

get_user_model ()

Em vez de se referir ao usuário diretamente, você deve referenciar o modelo do usuário usando django.contrib.auth.get_user_model (). Este método retornará o modelo de usuário ativo no momento - o modelo de usuário personalizado, se houver um especificado, ou usuário, caso contrário.

Ao definir uma chave estrangeira ou relações muitos para muitos para o modelo de Usuário, você deve especificar o modelo personalizado usando a configuração AUTH_USER_MODEL.

Estou confuso com o texto acima. Devo estar fazendo isso:

author = models.ForeignKey(settings.AUTH_USER_MODEL)

ou isto...

author = models.ForeignKey(get_user_model())

Ambos parecem funcionar.

Prometeu
fonte

Respostas:

85

O uso settings.AUTH_USER_MODELatrasará a recuperação da classe do modelo real até que todos os aplicativos sejam carregados. get_user_modeltentará recuperar a classe do modelo no momento em que seu aplicativo for importado pela primeira vez.

get_user_modelnão pode garantir que o Usermodelo já esteja carregado no cache do aplicativo. Pode funcionar em sua configuração específica, mas é um cenário de acerto e erro. Se você alterar algumas configurações (por exemplo, a ordem de INSTALLED_APPS), pode muito bem interromper a importação e você terá que gastar mais tempo depurando.

settings.AUTH_USER_MODEL irá passar uma string como o modelo de chave estrangeira e se a recuperação da classe do modelo falhar no momento em que esta chave estrangeira for importada, a recuperação será atrasada até que todas as classes do modelo sejam carregadas no cache.

knbk
fonte
7
Concretamente, você pode ter problemas de importação circular com models.ForeignKey (get_user_model ())
Chris Clark
2
Esta seção da documentação diz "De modo geral, você deve referenciar o modelo de usuário com a AUTH_USER_MODELconfiguração no código que é executado no momento da importação. get_user_model()Só funciona depois que o Django importou todos os modelos."
Hamish Downer
7
Então, concretamente, em funções (visualizações, métodos de modelo / serializador / formulário), use get_user_model(), para uso de atributos de classe AUTH_USER_MODEL?
Nick T
51

Novo desde Django 1.11.

Desde Django 1.11 você pode usar get_user_model()em ambos os casos! Portanto, se você não quiser se preocupar mais com isso, basta levá-lo.

"em ambos os casos" significa: se você precisa do modelo de usuário para acessar seus atributos, bem como se deseja definir uma relação ForeignKey / ManyToMany.

Do changelog :

get_user_model () agora pode ser chamado no momento da importação, mesmo em módulos que definem modelos.

então ... ainda há um motivo para usar settings.AUTH_USER_MODEL? Bem, os documentos ainda recomendam o settings.AUTH_USER_MODEL(que é uma string) para definir relações, mas sem dar uma razão explícita. Pode ser benéfico para o desempenho, mas não parece importar muito.

Exemplo de código:

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
fonte
Obrigado por apontar que get_user_model()pode ser chamado no momento da importação; no entanto, Django ainda avisa que os usuários definem relações de chave estrangeira e muitos para muitos usando AUTH_USER_MODEL
kevins
2
obrigado por apontar esta recomendação, de alguma forma eu a esqueci ao escrever a resposta, mas agora a encontrei. Tentei integrar isso na resposta (ainda favorável get_user_model, especialmente para os leitores que estão confusos sobre a distinção)
Ilja
7

Desde Django 1.11, get_user_model()na verdade usa 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
fonte
-11

Uma maneira de voltar ao modelo de usuário padrão se AUTH_USER_MODEL não estiver definido:

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

USER_MODEL = getattr(settings, 'AUTH_USER_MODEL', User)
sincronizar
fonte
7
AUTH_USER_MODELjá tem um padrão, então ele sempre será definido.
knbk
4
settings.AUTH_USER_MODEL também é uma string e seu substituto Useré um modelo
Matt