在Django 1.5自定義用戶模型中使用電子郵件作為用戶名字段導致FieldError



django-models django-1.5 (4)

伊恩,非常感謝你的聰明回應:)

但是,我已經“修補”了我的解決方案。

由於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'等),但也在一個更乾淨的User對象和數據庫表中。

使用USERNAME_FIELD在1.5中引入的靈活性不能用於在所有現有約束下實際創建靈活的用戶模型,這真是一種恥辱。

編輯:官方文檔中提供了一個全面的工作示例: https://docs.djangoproject.com/en/dev/topics/auth/customizing/#a-full-examplehttps://docs.djangoproject.com/en/dev/topics/auth/customizing/#a-full-example

我想使用電子郵件字段作為我的自定義用戶模型的用戶名字段。 我有以下自定義用戶模型子類化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-permittedhttps://docs.djangoproject.com/en/1.5/topics/db/models/#field-name-hiding-is-not-permitted
我怎樣才能做到這一點? (另外,然後命名字段“user_email”或類似的東西)


Answer #1

使用官方網站上的示例:

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

以下是符合管理員的自定義用戶應用的示例。 此用戶模型使用電子郵件地址作為用戶名,並具有所需的出生日期; 除了用戶帳戶上的簡單管理標誌之外,它不提供權限檢查。 除用戶創建表單外,此模型將與所有內置身份驗證表單和視圖兼容。 此示例說明了大多數組件如何協同工作,但不打算直接複製到項目中以供生產使用。


Answer #2

您可以編輯CustomUser以將email字段屬性更改為unique=True

將其添加到自定義用戶類的末尾,如下所示:

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

請注意,我們正在改變_unique並且不是unique因為後者是一個簡單的@property

這是一個黑客,我很想听到任何“官方”的答案來解決這個問題。


Answer #3

如果您的真實目標是唯一的“電子郵件”值,並忽略“用戶名”值,那麼您可以:

  • 填寫“用戶名”,例如sha256(user.email).hexdigest()[:30]
  • 以這種方式添加唯一性:

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

這導致:

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

按預期工作,非常簡單。





django-1.5