Позвольте мне начать с того, что я никогда не использовал какую-либо систему (Django или нет), где было много пользовательских таблиц, по одной для каждой роли пользователя. Всегда был только один пользовательский стол, совместно используемый каждым пользователем в системе, независимо от того, какие роли они играют. Когда вы не видите какой-то установки в дикой природе, это часто означает, что она не работает, поэтому мой совет: независимо от того, какую стратегию вы выбираете, или какова ваша бизнес-модель, всегда используйте одну и только одну модель Django для обработки аутентификации.
Если вам необходимо сохранить дополнительную информацию, относящуюся к пользователям, вам следует спросить себя, относится ли эта конкретная информация ко всем пользователям или только к некоторым типам пользователей. Например, «номер клиента» может относиться только к пользователям. В таких случаях вам лучше добавить модель профиля через отношение один к одному. Теперь, если дополнительная информация актуальна для всех пользователей (например, изображение аватара), лучше всего добавить дополнительное поле непосредственно в модель пользователя.
Вы можете иметь поле «роль» и использовать наследование или отношения «один к одному», чтобы связать эту базовую модель пользователя с моделями, специфичными для профиля. Я использовал как наследование, так и внешние ключи, и я предпочитаю внешний ключ модели профиля вместо наследования модели (наследование модели в любом случае реализовано с использованием взаимно-однозначных отношений, поэтому я предпочел бы быть в этом явным образом).
У вас может быть что-то вроде этого:
class User(models.Model):
ROLES = (
('customer', 'Customer'),
('vendor', 'Vendor'),
)
...
role = models.CharField(max_length=30, choices=ROLES)
vendor_profile = models.OneToOneField(
VendorProfile,
on_delete=models.CASCADE,
blank=True, null=True)
customer_profile = models.OneToOneField(
CustomerProfile,
on_delete=models.CASCADE,
blank=True, null=True)
...
@property
def profile(self):
if self.role == 'vendor':
if not self.vendor_profile_id:
self.vendor_profile = VendorProfile.objects.create()
if self.pk:
self.save()
return self.vendor_profile
if not self.customer_profile_id:
self.vendor_profile = CustomerProfile.objects.create()
if self.pk:
self.save()
return self.customer_profile
Но он не полностью прозрачен - например, если вам когда-либо приходится фильтровать набор запросов на основе определенных полей ролевых моделей, вы должны использовать vendor_profile__foo='Bar'
или customer_profile__foo='Bar'
в зависимости от роли пользователя. Возможно, вам также придется время от времени очищать висячие профили, поскольку с помощью указанного выше свойства вы можете создать профиль перед сохранением объекта пользователя.
В конце концов, есть много альтернатив для обработки нескольких типов пользователей, каждый из которых имеет свой компромисс, и это дело вкуса, но ИМХО распределение имен пользователей и паролей по нескольким моделям - плохая идея.