Django - Изменение имени пользователя Auth на Autofield нарушает код - PullRequest
0 голосов
/ 26 июня 2018

У меня есть приложение, в котором мне нужно изменить поле имени пользователя на Autofield.

Вариант использования - Я создаю приложение, в котором при создании пользователей имена пользователей должны быть похожи на CustomerID (целые числа) в банковских приложениях.

Есть 2 способа сделать это: -

1) Иметь id (PK), реализацию по умолчанию. Скопируйте id объекта и назначьте его столбцу имени пользователя, чтобы пользователи могли войти через идентификатор. Компромиссы

  • Два повторяющихся столбца.
  • Как бы я вызвал функцию create_user , так как для этого требуется имя пользователя.

2) Разрешить вход через идентификаторы, обновить AuthBackend и разрешить вход через идентификаторы тоже. Компромисс

  • Каким будет значение имени пользователя. Должен ли я сохранить его как электронную почту?
  • Не уверен, стоит ли разрешать вход в систему с помощью идентификаторов.

Pheww, достаточно для обсуждения. Теперь идет реализация (проблемная) часть. :-

Вот моя модель.

 class User(AbstractUser):
    username = models.BigAutoField(primary_key=True)
    user_id = models.UUIDField(default=uuid.uuid4, unique=True,
                               editable=False)

Модель не может иметь более одного AutoField, в результате username равно PK.

Миграции работали отлично. И таблица была создана.

Однако, когда я создаю пользователя, используя

User.objects.create_user(email=email, password=password)  #expecting the username to be auto-generated.

В нем говорится, что имя пользователя обязательно.

Я проверил Код Джанго UserManager Функция create_user и обновленный аргумент username=None

class CustomUserManager(UserManager):
    use_in_migrations = True

    def create_user(self, username=None, email=None, password=None,
                    **extra_fields):
        return super(CustomUserManager, self).create_user(username=username,
                                                          email=email,
                                                          password=password,
                                                          extra_fields=extra_fields)

По-прежнему выдается исключение: -

In [4]: User.objects.create_user(email='ab@ab.com', password='abcd1234@')
---------------------------------------------------------------------------
ValueError                                Traceback (most recent call last)
<ipython-input-4-de9c49dd635d> in <module>()
----> 1 User.objects.create_user(email='ab@ab.com', password='abcd1234@')

/Users/praful/Desktop/code/seynse/authentication/app/modules/users/models.py in create_user(self, username, email, password, **extra_fields)
     17                                                           email=email,
     18                                                           password=password,
---> 19                                                           extra_fields=extra_fields)
     20
     21

/Library/Frameworks/Python.framework/Versions/3.5/lib/python3.5/site-packages/django/contrib/auth/models.py in create_user(self, username, email, password, **extra_fields)
    157         extra_fields.setdefault('is_staff', False)
    158         extra_fields.setdefault('is_superuser', False)
--> 159         return self._create_user(username, email, password, **extra_fields)
    160
    161     def create_superuser(self, username, email, password, **extra_fields):

/Library/Frameworks/Python.framework/Versions/3.5/lib/python3.5/site-packages/django/contrib/auth/models.py in _create_user(self, username, email, password, **extra_fields)
    146         """
    147         if not username:
--> 148             raise ValueError('The given username must be set')
    149         email = self.normalize_email(email)
    150         username = self.model.normalize_username(username)

ValueError: The given username must be set

Что можно сделать в этом случае? Как я могу изменить имя пользователя на AutoField.

1 Ответ

0 голосов
/ 26 июня 2018

Вы должны создать собственный менеджер для своей модели пользователя. Он может наследоваться от BaseManager, но не от значения по умолчанию UserManager:

class CustomUserManager(BaseUserManager):
    use_in_migrations = True

    def _create_user(self, email, password, **extra_fields):
        """
        Create and save a user with the given email, and password.
        """
        email = self.normalize_email(email)
        user = self.model(email=email, **extra_fields)
        user.set_password(password)
        user.save(using=self._db)
        return user

    def create_user(self, email=None, password=None, **extra_fields):
        extra_fields.setdefault('is_staff', False)
        extra_fields.setdefault('is_superuser', False)
        return self._create_user(email, password, **extra_fields)

    def create_superuser(self, email, password, **extra_fields):
        extra_fields.setdefault('is_staff', True)
        extra_fields.setdefault('is_superuser', True)

        if extra_fields.get('is_staff') is not True:
            raise ValueError('Superuser must have is_staff=True.')
        if extra_fields.get('is_superuser') is not True:
            raise ValueError('Superuser must have is_superuser=True.')

        return self._create_user(email, password, **extra_fields)


class User(AbstractUser):
    username = models.BigAutoField(primary_key=True)
    user_id = models.UUIDField(default=uuid.uuid4, unique=True,
                               editable=False)

    objects = CustomUserManager()

    def __str__(self):
        return str(self.username)

Обратите внимание, что я полностью удалил username, поскольку нет смысла передавать явное значение для AutoField.

...