Почему менеджер create_superuser не работает в пользовательской модели пользователя?

Когда я пытаюсь создать суперпользователя в моем приложении, я получаю следующую ошибку:

Traceback (most recent call last):
  File "C:\Users\acer\Desktop\prod\DirCom\DirCom\manage.py", line 22, in <module>
    main()
  File "C:\Users\acer\Desktop\prod\DirCom\DirCom\manage.py", line 18, in main
    execute_from_command_line(sys.argv)
  File "C:\Users\acer\Desktop\prod\DirCom\venv\lib\site-packages\django\core\management\__init__.py", line 446, in execute_from_command_line
    utility.execute()
  File "C:\Users\acer\Desktop\prod\DirCom\venv\lib\site-packages\django\core\management\__init__.py", line 440, in execute
    self.fetch_command(subcommand).run_from_argv(self.argv)
  File "C:\Users\acer\Desktop\prod\DirCom\venv\lib\site-packages\django\core\management\base.py", line 402, in run_from_argv
    self.execute(*args, **cmd_options)
  File "C:\Users\acer\Desktop\prod\DirCom\venv\lib\site-packages\django\contrib\auth\management\commands\createsuperuser.py", line 88, in execute
    return super().execute(*args, **options)
  File "C:\Users\acer\Desktop\prod\DirCom\venv\lib\site-packages\django\core\management\base.py", line 448, in execute
    output = self.handle(*args, **options)
  File "C:\Users\acer\Desktop\prod\DirCom\venv\lib\site-packages\django\contrib\auth\management\commands\createsuperuser.py", line 183, in handle
    validate_password(password2, self.UserModel(**fake_user_data))
  File "C:\Users\acer\Desktop\prod\DirCom\venv\lib\site-packages\django\db\models\base.py", line 561, in __init__
    _setattr(self, field.name, rel_obj)
  File "C:\Users\acer\Desktop\prod\DirCom\venv\lib\site-packages\django\db\models\fields\related_descriptors.py", line 338, in __set__
    super().__set__(instance, value)
  File "C:\Users\acer\Desktop\prod\DirCom\venv\lib\site-packages\django\db\models\fields\related_descriptors.py", line 235, in __set__
    raise ValueError(
ValueError: Cannot assign "1": "User.persona" must be a "Persona" instance.

Перед этим createsuperuser шагом у меня есть пользовательский скрипт, который создает первую Персону проекта, и я пытаюсь назначить первую созданную персону с ID 1 этому суперпользователю.

Моя модель выглядит следующим образом:

class Persona(models.Model):
    """
        Clase para generar mi modelo de Persona que es el modelo
        previo a crear un usuario, en este modelo se guardan todos
        los datos personales
    """
    DEPENDENCIES_CHOICES = (
        ("1", "Rectorado - Gabinete"),
        ("2", "Vice Rectorado"),
        ("3", "Rectorado - Secretaria General"),
    )

    VINC_CHOICES = (("1", "Contratado"), ("2", "Permanente"),)

    gov_id = models.CharField("documento de identidad", max_length=50, unique=True)
    profile_picture = models.ImageField(
        "foto de perfil", upload_to="profiles", blank=True, null=True
    ) 
    email = models.EmailField("correo electrónico", max_length=254, unique=True) 
    first_name = models.CharField("nombres", blank=True, null=True, max_length=150)
    last_name = models.CharField("apellidos", blank=True, null=True, max_length=150)
    city = models.CharField("ciudad", blank=True, null=True,  max_length=30)
    phone = models.CharField("número de teléfono", blank=True, null=True, max_length=30)
    dependency = models.CharField("dependencia", blank=True, null=True, choices=DEPENDENCIES_CHOICES, max_length=2)
    vinc_type = models.CharField("tipo de vinculación", blank=True, null=True, choices=VINC_CHOICES, max_length=1)

    class Meta:
        verbose_name = "persona"

    def __str__(self):
        return f"{self.first_name} {self.last_name}"


class User(AbstractBaseUser, PermissionsMixin):
    """ 
        Clase para generar mi modelo personalizado de usuarios
        AbstractBaseUser es un modelo de Django que ya trae integradas
        las funcionalidades de autenticación y manejo de sesiones
        Los campos que AbstractBaseUser ya trae predefinidos son:
        -id
        -password
        -is_superuser
    """
    ROLE_CHOICES = (
        (1, "Director"),
        (2, "Analista"),
        (3, "Cliente"),
        (4, "Técnico"),
    )

    username = models.CharField("nombre de usuario", max_length=50, unique=True)
    persona = models.OneToOneField(Persona, on_delete=models.CASCADE, primary_key=True)
    role = models.PositiveSmallIntegerField("rol", choices=ROLE_CHOICES, default=ROLE_CHOICES[2][0])
    is_staff = models.BooleanField("staff", default=False)
    is_active = models.BooleanField("activo", default=True)
    date_joined = models.DateTimeField(default=timezone.now)

    # convierte el campo username en obligatorio por default
    USERNAME_FIELD = "username"

    # para que la terminal nos pida estos datos al crear un superuser
    REQUIRED_FIELDS = ['persona']

    objects = UserManager()

    class Meta:
        verbose_name = "usuario"
        ordering = ["-date_joined"]

И мой managers.py файл выглядит как

class UserManager(BaseUserManager, models.Manager):
    """
        este método sobreescribe la manera en que nuestro modelo
        de usuarios crea los nuevos usuarios
        es un método privado de la clase BaseUserManager por eso
        el nombre empieza con _
    """

    def _create_user(
        self, username, persona, password, is_staff, is_superuser, **extra_fields
    ):
        user = self.model(
            username=username,
            persona_id=persona,
            is_staff=is_staff,
            is_superuser=is_superuser,
            **extra_fields
        )
        user.set_password(password)
        user.save(using=self.db)
        return user

    """
        este es un método público que sirve para crear usuarios normales
        no administradores, desde el frente de la aplicación, este es el 
        método que usamos para crear los usuarios en el registro de la página web
    """

    def create_user(self, username, persona, password=None, **extra_fields):
        self._create_user(username, persona.id, password, False, False, **extra_fields)

    """
        este es un método público que permite crear super usuarios, es decir,
        administradores con todos los permisos. Podemos crear usuarios desde
        la línea de comandos ejecutando python manage.py createsuperuser
    """

    def create_superuser(self, username, persona, password=None, **extra_fields):
        return self._create_user(
            username, persona, password, True, True, **extra_fields
        )

Я уже пытаюсь использовать

def create_superuser(self, username, persona, password=None, **extra_fields:
        p = Persona.objects.get(pk=persona)
        return self._create_user(
            username, p, password, True, True, **extra_fields
        )

Но это тоже не работает. Есть идеи?

Сценарий create-superuser всегда возвращает объект типа User, когда вы назначаете суперпользователя типу любой модели в вашем проекте, вы получите ошибку несоответствия, где User не тот же тип, что и объект вашей модели

Вместо того чтобы иметь модель Persona вместе с моделью User, вы можете рассматривать пользователя как Persona и настроить модель создания пользователя со всеми атрибутами Persona, а также контролировать флаг is_superuser .

основным отличием в случае суперпользователя является флаг is_superuser, установленный в true Вам нужно создать метод, который создает объект Persona-Like User Object и присвоить флаг is_superuser этому объекту

Перейдите по ссылке, которая поможет вам создать собственную команду create user

Вернуться на верх