【问题标题】:User manager methods create() and create_user()用户管理器方法 create() 和 create_user()
【发布时间】:2012-07-18 15:02:19
【问题描述】:

我遇到了User 对象管理器的create() 方法的一些可疑行为。如果您使用此方法,则创建 User 对象似乎不需要 password 字段。结果你得到User 和空白password。如果您使用create_user 方法并且未指定password,它会创建带有不可用密码的User(通过set_unusable_password())。

当您尝试在没有password 的情况下创建用户时,我不确定为什么create() 方法不raise exception - 在文档中指定此字段是必需的。 create() 方法/文档有问题吗?

【问题讨论】:

    标签: django django-users django-managers


    【解决方案1】:

    这正是用户模型具有用于创建用户的UserManager.create_user() 方法的自定义管理器的原因。在User 实例上使用QuerySet.create() 方法有两个问题:

    1. 如果您运行管理命令python manage.py sql,请注意auth_user 架构:

      CREATE TABLE "auth_user" (
          ...
          "password" varchar(128) NOT NULL,
          ...
      )
      

      在 SQL 中,空字符串'' 不等于NULL,即ISNULL('') != TRUE

    2. QuerySet.create()QuerySet.update() 不触发模型验证。模型验证仅在 ModelForm 实例调用 Model.full_clean() 实例方法时发生。

      在直接使用QuerySet API 的上下文中引发验证错误在 Django 中毫无意义。这就是为什么您可以执行 User.objects.create(username='foo', password='') 之类的操作,即使 CharField().validate(value='', None) 会为空字符串引发 ValidationError

    由于上述原因,您应该推迟使用 User.objects.create() 并依赖模型自定义管理器提供的 User.objects.create_user() 方法。

    【讨论】:

    • 如果我不使用 ModelForm 并想触发模型验证怎么办?
    【解决方案2】:

    查看django的源码User模型,有一个自定义管理器,sn-p:

    class UserManager(models.Manager):
        # ...   
        def create_user(self, username, email=None, password=None):
            """
            Creates and saves a User with the given username, email and password.
            """
            now = timezone.now()
            if not username:
                raise ValueError('The given username must be set')
            email = UserManager.normalize_email(email)
            user = self.model(username=username, email=email,
                              is_staff=False, is_active=True, is_superuser=False,
                              last_login=now, date_joined=now)
    
            user.set_password(password)
            user.save(using=self._db)
            return user
    

    【讨论】:

    • 我了解 create_user 不需要密码。如果您针对某些外部源进行身份验证,它已经实现。我只是认为这对于用户的经理 create() 方法来说是不合适的行为。
    • 否,因为用户定义了自定义管理器但使用相同的变量“对象”创建
    猜你喜欢
    • 2013-11-29
    • 2016-01-29
    • 1970-01-01
    • 2013-11-28
    • 1970-01-01
    • 2016-08-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多