Django自定义用户模型和用户管理器

8
我正在使用Django 1.5构建一个Web应用程序。我正在使用自定义的User模型和自定义的UserManager。
我遵循了官方Django文档的说明和示例。
现在,当我尝试通过 UserManager.create_user(...) 创建新用户时,出现了NoneType错误:看起来UserManager的属性models是None类型的。
我认为我已经在User模型中正确设置了UserManager(objects = UserManager())。
我真的不知道我犯了什么错误。 我和我的编码伙伴都是Django的新手。也许你可以帮我们解决这个问题。
以下是代码:
class UserManager(BaseUserManager):
"""
    create a new user

    @param username:  the name for the new user
    @param password:  the password for the new user. if none is provided a random password is generated
    @param person:    the corresponding person object for this user
"""
def create_user(self, username, person, password=None):
    if not username:
        raise ValueError('User must have a valid username')

    user = self.model(username=username, created=datetime.now(), must_change_password=True, deleted=False, person=person)

    user.set_password(password)
    user.save(using=self._db)
    return user

class User(AbstractBaseUser):
    ## the id of the user. unique through the application
    user_id     =   models.AutoField(primary_key=True)
    ## the name of the user. unique through the application
    username    =   models.CharField(max_length=32, unique=True)
    ## the date when the user was created
    created     =   models.DateTimeField()
    ## iff this is true the user must set a new password at next login
    must_change_password    =   models.BooleanField(default=True)
    ## iff true the user is marked as deleted and can not login
    deleted     =   models.BooleanField(default=False)
    ## iff true the user is admin and has all permissions. use with care!
    is_admin = models.BooleanField(default=False)
    ## reference to the person entity that is linked to this specific user
    person      =   models.ForeignKey(Person)
    ## indicates if the user is active or not
    active    =    models.BooleanField(default=True)

    ## define the user manager class for User
    objects     =   UserManager()

    # necessary to use the django authentication framework: this field is used as username
    USERNAME_FIELD  =   'username'

在UserManager的create_user()方法中,在第user = self.model(..)行出现了NoneType错误。

5个回答

9
创建新用户时,不应调用 UserManager.create_user(...) 。相反,您应该使用:

from django.contrib.auth import get_user_model
get_user_model().objects.create_user(...)

这是django管理器的工作方式。您可以在此处阅读文档。

9

我也遇到了保存自定义用户模型的问题,花费了一段时间才弄清楚。

我认为你代码中重要的一行是:

objects     =   UserManager()

在 User 类内部,因此为了保存新用户,您需要调用

new_user=User.objects.create_user(args, args, args, etc)

"对象"是调用UserManager类并在Django中称为管理器的项目。

1
请解释一下为什么这个方法不好,谁给回答投了反对票。 - deathangel908

2

更新解决方案时要注意以下重要事项… 如果你遇到了这种问题,你可能已经尝试了多种网络上的解决方案,告诉你需要在settings.py中添加AUTH_USER_MODEL=users.CustomUser,然后在调用Userviews.pyforms.py和其他任何文件中添加以下代码:

最初的回答:

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

当你遇到错误时,你会摸摸头。

最初的回答:

Manager isn't available; 'auth.User' has been swapped for 'users.User'

每当您的代码引用User时,例如:

最初的回答:

User.objects.get()

因为你已经在自定义用户类中使用了 objects = UserManager()UserManager 是你自定义的扩展了 BaseUserManager 的管理器的名称)。
嗯,事实证明(感谢 @Aldarund)这样做:
User = get_user_model() # somewhere at the top of your .py file
# followed by
User.objects.get() # in a function/method of that same file

不等同于:

原始答案

get_user_model().objects.get() # without the need for User = get_user_model() anywhere

也许不是很直观,但在Python中,执行User = get_user_model()一次并不能使User在随后的调用中被定义(即它不会像在C/C++背景下所期望的那样变成一种“常量”;这意味着执行User = get_user_model()发生在导入时,但在该文件中随后调用类或函数/方法之前就被取消引用了)。
因此,总结一下,在所有引用User类的文件中(例如调用User.objects.get()User.objects.all()User.DoesNotExist等函数或变量):
# Add the following import line
from django.contrib.auth import get_user_model

# Replace all references to User with get_user_model() such as...
user = get_user_model().objects.get(pk=uid)
# instead of  user = User.objects.get(pk=uid)
# or
queryset = get_user_model().objects.all()
# instead of queryset = User.objects.all()
# etc...

希望这能帮助其他人节省时间...

最初的回答:

2

由于我没有足够的声望来发表评论,所以我必须添加一个答案。但是,@Aldarund答案中的链接根本没有描述如何使用get_user_model()。然而,这个链接应该会有帮助...


0
在我的情况下,如果你得到了 "manager_method" missing 1 required positional argument: 'self' django 错误,你应该注意到与 model.Manager 不同,UserManager 需要设置如下。
from django.contrib.auth.models import AbstractUser, UserManager
from django.db.models import Q

class CostumUserManager(UserManager ):
    
    def authors(self):
        return self.filter(Q(is_author=True) | Q(is_superuser=True))


class User(AbstractUser):
    is_author = models.BooleanField(default=False, )


    objects = CostumUserManager() # Use () in end of it


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