Что лучше для создания нескольких типов пользователей в Django? Абстрактные классы или прокси-модели?

Я хочу создать несколько типов пользователей в Django. Типы пользователей: 'Admin', 'Company' и 'Individual'. Следует ли мне использовать абстрактные модели или прокси-модели для этого требования.

Я уже делал это, используя прокси-модели. Как это можно сделать, используя абстрактные модели? Является ли один из них лучше другого? Если да, то чем?

Вот как я реализовал это, используя прокси-модели.

models.py:

class User(AbstractBaseUser, PermissionsMixin):
    id = models.AutoField(primary_key=True)
    email = models.EmailField(max_length=150, unique=True, null=False, blank=False)
    role = models.CharField(max_length=50, choices=Role.choices, null=False, blank=True)
    is_staff = models.BooleanField(null=False, default=False)
    is_active = models.BooleanField(null=False, default=True)
    is_superuser = models.BooleanField(null=False, default=False)

    objects = AccountManager()

    USERNAME_FIELD = "email"

    def __str__(self):
        return self.email

    def has_perm(self, perm, obj=None):
        return self.is_staff

    def has_module_perms(self, app_label):
        return self.is_superuser

class Admin(User):
    objects = AdminManager()

    class Meta:
        proxy = True

    def custom_method_for_admin_only(self):
        return something


class AdminProfile(models.Model):
    admin = models.OneToOneField(
        Admin, on_delete=models.CASCADE, related_name="admin_profile"
    )
    first_name = models.CharField(max_length=50, null=False, blank=False)
    middle_name = models.CharField(max_length=50, null=True, blank=True)
    last_name = models.CharField(max_length=50, null=False, blank=False)

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

class Company(User):
    objects = CompanyManager()

    class Meta:
        proxy = True

    def custom_method_for_company_only(self):
        return something


class CompanyProfile(models.Model):
    company = models.OneToOneField(
        Company, on_delete=models.CASCADE, related_name="company_profile"
    )
    name = models.CharField(max_length=50, null=False, blank=False)
    is_verified = models.BooleanField(default=False, null=False, blank=True)
    logo = models.ImageField(upload_to="images/", null=True, blank=True)

    def __str__(self):
        return self.name

class Individual(User):
    objects = IndividualManager()

    class Meta:
        proxy = True

class IndividualProfile(models.Model):
    individual = models.OneToOneField(
        Individual, on_delete=models.CASCADE, related_name="individual_profile"
    )
    first_name = models.CharField(max_length=50, null=False, blank=False)
    middle_name = models.CharField(max_length=50, null=True, blank=True)
    last_name = models.CharField(max_length=50, null=False, blank=False)

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

А менеджеры для моделей будут выглядеть примерно так:

managers.py:

Я уже делал это, используя прокси-модели. Как это можно сделать, используя абстрактные модели? Является ли одна из них лучше другой? Если да, то чем?

Please don't. It will make things a lot more complicated. If a user wants to authenticate, you will have to look through three tables. The AuthenticationMiddleware [Django-doc] that thus assigns request.user based on the session id, will also complicate matters.

A typical use case is that objects refer to the user that is the "owner" of an item, so such ForeignKeys now will have to refer to three possible models resulting in either three ForeignKeys [Django-doc], a GenericForeignKey [Django-doc], or some complicated logic that first has to decypher which of the three.

Я думаю, что, вероятно, самый бережливый способ сделать трех возможных пользователей с дополнительными данными - это работать с конкретным наследованием моделей:

class IndividualProfile(User):
    dob = models.DateField(null=True)

и затем мы можем определить User, которые являются индивидуумами с:

User.objects.filter(individualprofile__isnull=False)

Итак, все ваши типы пользователей на самом деле являются пользователями. Поэтому имеет смысл иметь их в виде User, и вам нужно будет обрабатывать их различия. Я бы предположил, что имеет смысл хранить их тип и создать абстрактную модель для UserType или что-то в этом роде, обрабатывая все ваши типы аналогично внутри этой абстрактной модели и расширяя эту абстрактную модель конкретными моделями ваших фактических типов для обработки их различий.

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