Django使用get_user_model与settings.AUTH_USER_MODEL
阅读Django文档:
get_user_model()
在使用用户模型时,不要直接提到User,而是应该用
django.contrib.auth.get_user_model()
来引用用户模型。这个方法会返回当前活跃的用户模型——如果有自定义的用户模型,它会返回那个;如果没有,就返回默认的User模型。当你定义与用户模型的外键或多对多关系时,应该通过
AUTH_USER_MODEL
设置来指定自定义模型。
我对上面的内容有点困惑。我应该这样做:
author = models.ForeignKey(settings.AUTH_USER_MODEL)
还是这样做...
author = models.ForeignKey(get_user_model())
这两种方法似乎都可以。
7 个回答
我在书《Two Scoops of Django 3.x》中看到:
这样做不好,因为它容易导致导入循环。
不好的例子:
owner = models.OneToOneField(get_user_model()) -> 不好,别这么做
settings.AUTH_USER_MODEL
返回的是一个字符串(用户模型的位置),比如说 user_accounts.User
。
get_user_model()
返回的是实际的模型类,而不是字符串。
所以在需要用户模型的时候,使用 get_user_model()
。如果你需要它的位置(以字符串形式表示的 module.model
),那就用 settings.AUTH_USER_MODEL
。
从Django 1.11开始,get_user_model()
这个函数实际上是用来获取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
)
自Django 1.11以来的新功能
从Django 1.11开始,你可以在两种情况下使用get_user_model()
!所以如果你不想再纠结这个问题,直接用它就行了。
这里的“在两种情况下”是指:如果你需要用户模型来访问它的属性,或者你想定义一个外键(ForeignKey)或多对多关系(ManyToMany)。
来自更新日志的内容:
现在可以在导入时调用get_user_model(),即使是在定义模型的模块中。
那么... 还有必要使用settings.AUTH_USER_MODEL
吗?文档仍然推荐使用settings.AUTH_USER_MODEL
(这是一个字符串)来定义关系,但没有给出明确的理由。可能对性能有好处,但似乎影响不大。
代码示例:
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!
...
)
使用 settings.AUTH_USER_MODEL
会让你在所有应用加载完成之前,无法立即获取到实际的用户模型类。而 get_user_model
则会在你的应用第一次被导入时,尽量去获取这个模型类。
不过,get_user_model
并不能保证 User
模型已经加载到应用的缓存中。它在你的特定环境下可能会正常工作,但也有可能不行。如果你更改了一些设置(比如 INSTALLED_APPS
的顺序),就可能导致导入失败,这样你就得花额外的时间去调试了。
而 settings.AUTH_USER_MODEL
会把一个字符串作为外键模型传递,如果在导入这个外键时获取模型类失败,那么获取过程会被延迟,直到所有模型类都加载到缓存中。