Почему менеджер 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