24

我想使用电子邮件字段作为自定义用户模型的用户名字段。我有以下自定义用户模型继承 Django 的 AbstractUser 模型:

class CustomUser(AbstractUser):
    ....
    email = models.EmailField(max_length=255, unique=True)

    USERNAME_FIELD = 'email'

但是当我跑步时

python manage.py sql myapp

我收到以下错误:

FieldError:类“CustomUser”中的本地字段“email”与基类“AbstractUser”中名称相似的字段冲突

我首先包含我自己的电子邮件字段的原因是为其添加unique=True选项。否则我得到:

myapp.customuser:USERNAME_FIELD 必须是唯一的。将 unique=True 添加到字段参数。

现在,关于这个: https
://docs.djangoproject.com/en/1.5/topics/db/models/#field-name-hiding-is-not-permitted 我怎样才能做到这一点?(然后将字段命名为“user_email”或类似名称)

4

4 回答 4

36

伊恩,非常感谢你的聪明回应:)

但是,我已经为我“修补”了一个解决方案。

由于AbstractUser还有一个username对我来说完全不需要的领域,
我决定创建我的“自己的” AbstractUser

通过子类化AbstractBaseUserPermissionsMixin我保留了大部分 User 模型的内置方法,而无需添加任何代码。

我还利用这个机会创建了一个自定义Manager来消除在 username现场的使用:

from django.contrib.auth.models import AbstractBaseUser, PermissionsMixin, BaseUserManager

class CustomUser(AbstractBaseUser, PermissionsMixin):
     ....
     email = models.EmailField(max_length=255, unique=True)
     first_name = ...
     last_name = ...
     is_active = ...
     is_staff = ...
     ....

     objects = CustomUserManager()

     USERNAME_FIELD = 'email'


class CustomUserManager(BaseUserManager):
     def create_user(self, email, password=None, **extra_fields):
          .....

     def create_superuser(self, email, password, **extra_fields):
          .....

这个解决方案确实会导致重复一些 Django 的内置代码(主要是已经存在的模型字段,AbstractUser例如“first_name”、“last_name”等),但也会导致更清晰的用户对象和数据库表中的重复。

遗憾的是 1.5 中引入的 flexibily 不能用于在所有现有约束下实际创建USERNAME_FIELD灵活的 User 模型。

编辑:官方文档中有一个全面的工作示例:https ://docs.djangoproject.com/en/dev/topics/auth/customizing/#a-full-example

于 2013-03-25T00:30:56.997 回答
10

如果您的真正目标是唯一的“电子邮件”值,而忽略“用户名”值,那么您可以:

  • 填写“用户名”,例如sha256(user.email).hexdigest()[:30]
  • 以这种方式添加唯一性:

    class User(AbstractUser):
        class Meta:
            unique_together = ('email', )
    

这导致:

CREATE TABLE "myapp_user" (
    ...
    "email" varchar(75) NOT NULL,
    UNIQUE ("email")
)

按预期工作,并且非常简单。

于 2013-07-03T17:40:49.237 回答
9

您可以编辑您的CustomUser以将email字段属性更改为unique=True.

将其添加到自定义用户类的末尾,如下所示:

class CustomUser(AbstractUser):
    ...
    USERNAME_FIELD = 'email'
    ...
CustomUser._meta.get_field_by_name('email')[0]._unique=True

请注意,我们正在更改_unique,而不是unique因为后者是简单的@property.

这是一个黑客,我很想听到任何“官方”的答案来解决这个问题。

于 2013-03-24T20:50:49.717 回答
2

使用来自官方网站的示例:

https://docs.djangoproject.com/en/1.7/topics/auth/customizing/#a-full-example

这是一个符合管理员要求的自定义用户应用程序的示例。此用户模型使用电子邮件地址作为用户名,并具有所需的出生日期;除了用户帐户上的简单管理标志外,它不提供权限检查。该模型将与所有内置的身份验证表单和视图兼容,除了用户创建表单。此示例说明了大多数组件如何协同工作,但并非旨在直接复制到项目中以供生产使用。

于 2014-10-24T23:48:44.107 回答