Django - 多个用户配置文件
Posted
技术标签:
【中文标题】Django - 多个用户配置文件【英文标题】:Django - Multiple User Profiles 【发布时间】:2012-03-27 20:28:06 【问题描述】:最初,我的 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
与settings.py
中设置的AUTH_PROFILE_MODULE = 'accounts.UserProfile'
配合得很好。
但是,我的网站中有两种不同类型的用户,个人和公司,每个用户都有自己独特的属性。例如,我希望我的个人用户只有一个用户,因此拥有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
变量都混合在一起,然后我会在必要时使用所需的模型。但这对我来说看起来并不干净,我宁愿将它们隔离并在适当的地方使用适当的模型。
对干净的方法有什么建议吗?
【问题讨论】:
inheritance 呢? 我可以将UserProfile
抽象化并让IndivProfile
和CorpProfile
继承自UserProfile
。这仍然不能解决AUTH_PROFILE_MODULE
的问题。它会指向哪一个?
如何将企业+个人+帐户类型字段添加到一个模型中?我认为如果你只有两种类型可能没问题,但如果你有超过 2 种或者这些配置文件非常不同,则可能会很糟糕。
这不能解决user
对每种类型都不同的问题。请阅读帖子,我已经提到我可以做到,但我正在寻找一种干净的方法。
一个小问题:如果您有多个用户与同一个公司资料相关,您不能在公司资料上使用ForeignKey
字段对其进行建模。
【参考方案1】:
值得尝试使用直通字段。它背后的想法是将 UserProfile 模型用作 CorpProfile 或 IndivProfile 模型的直通模型。这样,只要将公司或个人资料链接到用户,就会创建它:
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,但另一方面我觉得这个想法很吸引人。 :)
【讨论】:
我试过运行它,但它显示invalid keyword argument 'through'
错误。我现在正在工作,无法获得确切的措辞。
糟糕,仅适用于多对多关系。现在看起来像另一个不太干净的解决方案。但我认为 Aamir 已经提出了一个非常简单的解决方案。
@marue,这个答案应该被完全删除吗?这是不正确的,似乎令人困惑。
@BasicWolf 应该删了吧。【参考方案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 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 %
希望这会带你到某个地方。谢谢!
【讨论】:
不推荐使用OneToOne 而不是ForeignKey? 指定外键也与oneToOne关系有关。 没有 OneToOne 你应该写:try: profile.corporate_user_set.all()[0]
为了明确一点:OneToOneField 只是 ForeignKey(unique=True) 的 Django 内部包装器。所以 OTO 不只是有点相关,它和 ForeignKey 完全一样。
@marue 你错了! OneToOneField 不仅仅是 ForeignKey(unique=True) 的内部包装,这表明它们是等价的......它们不是! ***.com/a/5891861/2722398【参考方案3】:
我是这样做的。
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
。
【讨论】:
您是如何存储不常见字段的?你能展示一下代码吗? 近 4 年后回头看 - 你有什么不同的做法吗?以上是关于Django - 多个用户配置文件的主要内容,如果未能解决你的问题,请参考以下文章