Что лучше для создания нескольких типов пользователей в 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 ForeignKey
s now will have to refer to three possible models resulting in either three ForeignKey
s [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
или что-то в этом роде, обрабатывая все ваши типы аналогично внутри этой абстрактной модели и расширяя эту абстрактную модель конкретными моделями ваших фактических типов для обработки их различий.