Подтвердить что ты не робот

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), а для Corporate я хотел бы, чтобы у них было несколько пользователей, связанных с одним и тем же профилем, поэтому вместо этого я имел бы 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, которые все смешиваются вместе, а затем я буду использовать необходимые, где это необходимо. Но это просто не выглядит чистым для меня, я бы предпочел, чтобы они были разделены и использовали подходящую модель в соответствующем месте.

Любые предложения по чистым образом?

4b9b3361

Ответ 1

Я сделал это таким образом.

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 и моей модели Profile. В случае наличия несовместимых атрибутов я создам новую модель и свяжу ее с Profile.

Ответ 2

Вы можете сделать это следующим образом. Имейте профиль, который будет содержать общие поля, которые необходимы в обоих профилях. И вы уже сделали это, создав класс 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 %}

Надеюсь, это приведет вас куда-нибудь. Благодаря

Ответ 3

Возможно, стоит попробовать использовать сквозное поле. Идея этого заключается в использовании модели 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 или того, что вы хотите.

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