Django-Несколько Профилей Пользователей
Первоначально я начал свой UserProfile следующим образом:
from django.db import models
from django.contrib.auth.models import User
class UserProfile(models.Model):
user = models.OneToOneField(User)
verified = models.BooleanField()
mobile = models.CharField(max_length=32)
def __unicode__(self):
return self.user.email
который отлично работает вместе с AUTH_PROFILE_MODULE = 'accounts.UserProfile'
установить в settings.py
.
тем не менее, у меня есть два разных типа пользователей на моем сайте, физические и корпоративные, каждый из которых имеет свои уникальные атрибуты. Например, я хотел бы, чтобы мои отдельные пользователи имели только одного пользователя, следовательно, имея user = models.OneToOneField(User)
, и для корпоративного я хотел бы, чтобы у них было несколько пользователей, связанных с одним профилем, поэтому я бы user = models.ForeignKey(User)
вместо.
поэтому я подумал о разделении модели на две разные модели,IndivProfile
и CorpProfile
, оба наследуют от UserProfile
при перемещении атрибутов конкретной модели в соответствующие подмодели. Мне кажется, что это хорошая идея и, вероятно, сработает, однако я не смогу указать AUTH_PROFILE_MODULE
таким образом, поскольку у меня есть два профиля пользователей, которые будут отличаться для разных пользователей.
я также думал о том, чтобы сделать это наоборот, имея UserProfile
наследовать от нескольких классов (моделей), что-то вроде этого:
class UserProfile(IndivProfile, CorpProfile):
# some field
def __unicode__(self):
return self.user.email
таким образом я бы поставил AUTH_PROFILE_MODULE = 'accounts.UserProfile'
и решить свои проблемы. Но это не похоже на то, что это сработает, так как наследование в python работает слева направо и все переменные в IndivProfile
будет доминирующим.
конечно, я всегда могу иметь одну модель с IndivProfile
и CorpProfile
переменные все смешанные вместе, а затем я бы использовал необходимые, где это необходимо. Но это просто не выглядит чистым для меня, я бы предпочел, чтобы они были разделены и использовали соответствующую модель в соответствующем месте.
любые предложения очистить как это сделать?
3 ответов
вы можете сделать это следующим образом. Имейте профиль, который будет содержать общие поля, которые необходимы в обоих профилях. И вы уже сделали это, создав класс UserProfile
.
class UserProfile(models.Model):
user = models.ForeignKey(User)
#some common fields here, which are shared among both corporate and individual profiles
class CorporateUser(models.Model):
profile = models.ForeignKey(UserProfile)
#corporate fields here
class Meta:
db_table = 'corporate_user'
class IndividualUser(models.Model):
profile = models.ForeignKey(UserProfile)
#Individual user fields here
class Meta:
db_table = 'individual_user'
здесь нет ракетостроения. Просто есть ключевое слово, которое будет различать корпоративный профиль или индивидуальный профиль. Например. Считайте, что пользователь регистрируется. Затем есть поле в форме, которое будет различать, подписывается ли пользователь на корпоративный или нет. И используйте это ключевое слово (параметр запроса), чтобы сохранить пользователя в соответствующей модели.
затем позже, когда вы хотите проверить, что профиль пользователя является корпоративным или индивидуальным, вы можете проверить его, написав небольшую функцию.
def is_corporate_profile(profile):
try:
profile.corporate_user
return True
except:
return False
#If there is no corporate profile is associated with main profile then it will raise exception and it means its individual profile
#you can use this function as a template function also to use in template
{%if profile|is_corporate_profile %}
надеюсь, это приведет вас куда-то. Спасибо
Я сделал это таким образом.
PROFILE_TYPES = (
(u'INDV', 'Individual'),
(u'CORP', 'Corporate'),
)
# used just to define the relation between User and Profile
class UserProfile(models.Model):
user = models.ForeignKey(User)
profile = models.ForeignKey('Profile')
type = models.CharField(choices=PROFILE_TYPES, max_length=16)
# common fields reside here
class Profile(models.Model):
verified = models.BooleanField(default=False)
в итоге я использовал промежуточную таблицу, чтобы отразить связь между двумя абстрактными моделями,User
который уже определен в Django, и my Profile
модель. В случае наличия атрибутов, которые не являются общими, я создам новую модель и свяжу ее с Profile
.
может быть стоит попробовать использовать через поле. Идея заключается в использовании модели UserProfile как сквозной модели для моделей CorpProfile или IndivProfile. Таким образом, он создается, как только профиль Corp или Indiv связан с пользователем:
from django.db import models
from django.contrib.auth.models import User
class UserProfile(models.Model):
user = models.ForeignKey(User)
profile = models.ForeignKey(Profile, related_name='special_profile')
class Profile(models.Model):
common_property=something
class CorpProfile(Profile):
user=models.ForeignKey(User, through=UserProfile)
corp_property1=someproperty1
corp_property2=someproperty2
class IndivProfile(Profile):
user=models.ForeignKey(User, through=UserProfile, unique=true)
indiv_property1=something
indiv_property2=something
Я думаю, что таким образом можно установить AUTH_PROFILE_MODULE = 'accounts.UserProfile'
, и каждый раз, когда вы создаете CorpProfile или IndivProfile, связанный с реальным пользователем, создается уникальная модель UserProfile. Затем вы можете получить доступ к этому с запросы db или все, что вы хотите.
Я не тестировал это, поэтому никаких гарантий. Это может быть немного избито, но с другой стороны, я нахожу эту идею довольно привлекательной. :)