Подтвердить что ты не робот

Использование электронной почты в качестве поля имени пользователя в пользовательской модели пользовательской модели Django 1.5 в FieldError

Я хочу использовать поле электронной почты в качестве поля имени пользователя для моей пользовательской модели. У меня есть следующая пользовательская модель подкласса модели Django AbstractUser:

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

    USERNAME_FIELD = 'email'

Но когда я запустил

python manage.py sql myapp

Я получаю следующую ошибку:

FieldError: локальное поле "email" в классах "CustomUser" сталкивается с полем аналогичного имени из базового класса "AbstractUser"

Причина, по которой я включаю свое собственное поле электронной почты, в первую очередь - добавить к ней параметр unique=True. в противном случае я получаю:

myapp.customuser: USERNAME_FIELD должен быть уникальным. Добавить уникальный = Верно для параметров поля.

Теперь, в связи с этим: https://docs.djangoproject.com/en/1.5/topics/db/models/#field-name-hiding-is-not-permitted
Как может достичь этого? (другой, затем называя поле "user_email" или что-то в этом роде)

4b9b3361

Ответ 1

Ян, большое спасибо за умный ответ:)

Однако я уже "исправил" меня решение.

Так как AbstractUser также имеет поле username, которое для меня совершенно ненужно
Я решил создать свой "собственный" AbstractUser.

Подклассификация AbstractBaseUser и PermissionsMixin Я сохраняю большинство встроенных методов модели 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 с помощью USERNAME_FIELD, не может использоваться для актуальной создания гибкой модели пользователя при всех существующих ограничениях.

EDIT: в официальных документах есть подробный рабочий пример: https://docs.djangoproject.com/en/dev/topics/auth/customizing/#a-full-example

Ответ 2

Если ваша реальная цель - это уникальные значения "электронной почты" и игнорирование значений "имя пользователя", вы можете:

  • Заполните "имя пользователя", например. sha256(user.email).hexdigest()[:30]
  • Добавьте уникальность таким образом:

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

Это приводит к:

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

работает так, как ожидалось, и довольно просто.

Ответ 3

Вы можете изменить свой CustomUser, чтобы изменить атрибут поля email на unique=True.

Добавьте это в конец своего пользовательского класса, например:

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

Обратите внимание, что мы меняем _unique, а не unique, потому что последний является простым @property.

Это хак, и я хотел бы услышать любые "официальные" ответы, чтобы решить эту проблему.

Ответ 4

Используйте пример с официального сайта:

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

Вот пример пользовательского пользовательского приложения, совместимого с администратором. Эта модель пользователя использует адрес электронной почты в качестве имени пользователя и имеет необходимую дату рождения; он не обеспечивает проверку разрешений за пределами простого флага администратора в учетной записи пользователя. Эта модель будет совместима со всеми встроенными формами и представлениями auth, за исключением форм создания пользователя. Этот пример иллюстрирует, как большая часть компонентов работает вместе, но не предназначена для копирования непосредственно в проекты для использования в производстве.