Django 1.5:在models.py中访问自定义用户模型字段

7

我正在开发一个Django 1.5项目,其中包含自定义用户模型(我们称之为CustomUser)。另一个应用程序(SomeApp)需要引用这个自定义用户模型。根据Django文档的说明,在ForeignKey等情况下,应使用以下代码:

User = settings.AUTH_USER_MODEL 

然而,SomeApp.models中的一些函数需要访问以前被称为User.objects的内容。但是现在User是一个字符串而不是一个类,所以User.objects会失败。替代方案是:

from django.contrib.auth import get_user_model
User = get_user_model()

这段代码在其他模块中可以正常运行,但当我在SomeApp的models.py中使用时,Django会抛出以下错误:

ImproperlyConfigured("AUTH_USER_MODEL引用了未安装的模型'%s'" % settings.AUTH_USER_MODEL)

有什么想法吗?

编辑1-回溯信息:

Traceback (most recent call last):
  File "<console>", line 1, in <module>
  File "...\django-badger\badger\__init__.py", line 7, in <module>
    from badger.models import Badge, Award, Progress
  File "...\django-badger\badger\models.py", line 26, in <module>
    User = get_user_model()
  File "...\lib\site-packages\django\contrib\auth\__init__.py", line 127, in get_user_model
    raise ImproperlyConfigured("AUTH_USER_MODEL refers to model '%s' that has not been installed" % settings.AUTH_USER_MODEL)
ImproperlyConfigured: AUTH_USER_MODEL refers to model 'MyApp.AuthUser' that has not been installed

编辑2 - 安装应用程序设置:

INSTALLED_APPS = (
'django.contrib.auth',
'django.contrib.contenttypes',
'django.contrib.sessions',
'django.contrib.sites',
'django.contrib.messages',
'django.contrib.staticfiles',
'django.contrib.admin',
'django.contrib.admindocs',
'south',
'MyApp',   # this is where my user model is defined
'SomeApp', # I try to use get_user_model() in this app's models.py; doesn't work.
'social_auth',
)

你能发布完整的回溯吗? - jpic
你是如何在设置中定义AUTH_USER_MODEL的?用户位于哪个应用程序中,其类名是什么? - matino
@matino - 是的,在设置中定义了它。get_user_model()在除models.py之外的所有其他文件中都正常工作。我的自定义用户模型AuthUser在MyApp中定义(以本示例为例)。 - askvictor
我们能看到你的 INSTALLED_APPS 设置吗? - jpic
为什么在MyApp models.py中使用get_user_model()而不是直接引用类名? - matino
显示剩余2条评论
8个回答

11

我刚才也遇到了同样的问题,这是我的两分钱/解决方案。

如果您想在models.py中使用自定义用户模型,您将使用settings.AUTH_USER_MODEL作为外键,对于模型方法,您必须使用get_user_model(),但它必须在方法内部。它在外部不起作用,因为存在循环导入。

from django.conf import settings
from django.contrib.auth import get_user_model

class Event(models.Model):

    recipient = models.ForeignKey(settings.AUTH_USER_MODEL)
    ...

    def get_something(self):

        User = get_user_model()
        u = User.objects.get(id=...)
        ...

2
这是最终的答案。谢谢Freon! - Craig Labenz

10

这个很简单。我遇到了很多递归包含等问题... 当你添加一个 ForeignKey 时,最简单的方法是这样写:

user = models.ForeignKey(settings.AUTH_USER_MODEL, null=False, on_delete=models.CASCADE, verbose_name=_(u"User"))

如果你使用get_user_model,请不要像以前那样使用它。调用

User = get_user_model()

模块顶部会尝试导入您的User模型,但该模型可能未被“安装”。

相反,您有几个选择:

  • 在模块顶部写入

    User = get_user_model # 然后,您将需要使用User()代替User

  • 在有用的地方随处写入get_user_model()。始终在方法或函数中使用,永远不要直接在模型模块体中使用它。


这对我有用。我在文件顶部导入了get_user_model()。完全有道理。谢谢。 - Howie
在声明式代码中,你会如何处理这个问题?例如,一个UserSerializer类有一个Meta类,其中指定了模型。你不能将User模型的定义推迟到执行时间,因为整个定义在导入时解析。 - blueFast

3

确保您的自定义用户模型不是抽象的。


1

1
我认为这个来自SomeApp的导入会造成循环导入。这就是为什么在docs中有一个语句,类似于使用调用设置属性的ForeignKey。
至于我,当我使用django-filer应用程序时,我遇到了这个问题。在github上有一个commit来防止使用get_user_model()进行导入。你可以使用那里的代码作为修复问题的示例。
这个问题非常棘手,因为当你尝试从shell调用get_user_model()时,它会起作用。

0

我开始觉得需要一个解决方法 - 对于以下内容有任何评论吗? 在SomeApp/models.py中:

from django.contrib.auth.models import User as UserModel
try:
    from django.contrib.auth import get_user_model
except ImportError:  #django <= 1.4 doesn't have get_user_model so define our own
    def get_user_model():
        return UserModel
User = getattr(settings, 'AUTH_USER_MODEL', 'auth.User')
...
def SomeModel(models.Model):
    user = models.ForeignKey(User)  # using the name of the model
    def some_method(self, email):
        qs = get_user_model().objects.filter(email=email)  # using function call to get model class 

嘿@askvictor,你最终是如何解决这个问题的?我也遇到了同样的问题,但是在运行迁移时出现了问题,并且是在我的应用程序之后安装的软件包。 - tzenderman
@tzenderman - 我把项目暂停了一段时间,解决了这个问题 :-/ 对于迁移,我创建了一个中间迁移,并使用了 needed_by 或 depends_on 来解决相关问题:https://dev59.com/kHTYa4cB1Zd3GeqPwZbS - askvictor

0

您需要在settings.py中设置,

AUTH_USER_MODEL = "yourapp.CustomUser"

然后get_user_model() 将会起作用。这里有一个清晰的文档可供参考


它已经是这样了。get_user_model() 在 models.py 以外的其他文件中可以正常工作。 - askvictor
请检查您的INSTALLED_APPS的顺序。包含CustomUser的应用程序应该位于其他应用程序之上。详细说明在这里,https://code.djangoproject.com/ticket/19218 - Babu

0

你正在使用 South 0.8.3 吗?

请确保你至少在运行 South 0.8.4

GitHub 问题 South 发布 注释


网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接