27

最初,我像这样开始我的 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'与set in一起工作得很好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变量混合在一起,然后在必要时使用所需的模型。但这对我来说看起来并不干净,我宁愿将它们隔离并在适当的地方使用适当的模型。

任何关于这样做的干净方式的建议?

4

3 回答 3

25

您可以通过以下方式执行此操作。有一个配置文件,其中包含两个配置文件中必需的公共字段。你已经通过创建 class 来做到这一点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 CorporateUser.DoesNotExist:
        return False

# If there is no corporate profile is associated with main profile then it will raise `DoesNotExist` 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 %}

希望这会引导你到某个地方。谢谢!

于 2012-03-11T19:35:43.837 回答
9

我已经这样做了。

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.

于 2012-03-17T11:05:11.077 回答
-1

可能值得尝试使用直通字段。它背后的想法是将 UserProfile 模型用作 CorpProfile 或 IndivProfile 模型的直通模型。这样,只要将 Corp 或 Indiv Profile 链接到用户,就会创建它:

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 查询或任何您想要的方式访问它。

我没有测试过这个,所以不能保证。这可能有点hacky,但另一方面我觉得这个想法很吸引人。:)

于 2012-03-11T16:59:13.037 回答