在Django 1.5自定义用户模型中使用电子邮件作为用户名字段导致FieldError

OrP*_*rPo 22 django django-models django-1.5

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

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

    USERNAME_FIELD = 'email'
Run Code Online (Sandbox Code Playgroud)

但是当我跑步的时候

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"或类似的东西)

OrP*_*rPo 37

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

但是,我已经"修补"了我的解决方案.

既然AbstractUser有一个username对我来说完全
没必要的领域我决定创造我自己的"自己" AbstractUser.

通过子类化AbstractBaseUser,PermissionsMixin我保留了大多数用户模型内置方法,而无需添加任何代码.

我还利用这个机会创建了一个自定义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):
          .....
Run Code Online (Sandbox Code Playgroud)

这个解决方案确实导致重复一些Django的内置代码(主要是已经存在的模型字段,AbstractUser如'first_name','last_name'等),但也在一个更干净的User对象和数据库表中.

这是一个真正的耻辱,在1.5与引入的flexibily USERNAME_FIELD不能用于actualy创建下所有现有的约束灵活的用户模型.

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


Den*_*kov 9

如果您的真实目标是唯一的"电子邮件"值,并忽略"用户名"值,那么您可以:

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

    class User(AbstractUser):
        class Meta:
            unique_together = ('email', )
    
    Run Code Online (Sandbox Code Playgroud)

这导致:

CREATE TABLE "myapp_user" (
    ...
    "email" varchar(75) NOT NULL,
    UNIQUE ("email")
)
Run Code Online (Sandbox Code Playgroud)

按预期工作,非常简单.


Ian*_*Ian 8

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

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

class CustomUser(AbstractUser):
    ...
    USERNAME_FIELD = 'email'
    ...
CustomUser._meta.get_field_by_name('email')[0]._unique=True
Run Code Online (Sandbox Code Playgroud)

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

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