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 или все, что вы хотите.

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