戈多表继承VS指定明确的OneToOne关系模型
-
22-09-2019 - |
题
希望这一切的意义:)我会澄清通过的意见,如果必要的。此外,我尝试使用大胆的文本在这个问题,并将编辑出来,如果我(或您)找到这会让人分心。用这种方式...
使用django。普.授权使我们有用户和群组,除其他有用的事情,我不能没有的(如基本的通讯).
在我的程序,我有几种不同类型的用户。一个用户可能只有一个类型。那将会很容易地加以处理的团体,与一个小小的额外护理。 然而,这些不同的用户都是彼此相关的层次结构/合作关系。
让我们看看这些用户:-
校长-"顶级"用户
管理员-每个管理员报告的主体
协调员--每个协调员的报告给管理员
除了这些 还有其它用户的类型没有直接关系, 但可获得相关的。例如,"公司"是另一种类型的用户,可以有各种"产品",以及产品可以监督一个"协调员"."买方"是另一种类型的用户可购买的产品。
现在,所有这些 用户有多种其他属性,其中一些是共同所有类型的用户,其中有一些不同的只有一个用户的类型.例如,所有类型的用户必须要有一个地址。另一方面,唯一的主要用户属于"BranchOffice".
另一点,这是上面所述,是, 用户可以永远只能是一种类型.
该应用程序还 需要跟踪谁创建和/或修改的主体,管理员、协调员、公司、产品等等.(所以这就是两个链接到用户的模型。)
在这种情况下,这是一个好主意,使用Django的多表遗产如下:-
from django.contrib.auth.models import User
class Principal(User):
#
#
#
branchoffice = models.ForeignKey(BranchOffice)
landline = models.CharField(blank=True, max_length=20)
mobile = models.CharField(blank=True, max_length=20)
created_by = models.ForeignKey(User, editable=False, blank=True, related_name="principalcreator")
modified_by = models.ForeignKey(User, editable=False, blank=True, related_name="principalmodifier")
#
#
#
或者我应该去做这样的:-
class Principal(models.Model):
#
#
#
user = models.OneToOneField(User, blank=True)
branchoffice = models.ForeignKey(BranchOffice)
landline = models.CharField(blank=True, max_length=20)
mobile = models.CharField(blank=True, max_length=20)
created_by = models.ForeignKey(User, editable=False, blank=True, related_name="principalcreator")
modified_by = models.ForeignKey(User, editable=False, blank=True, related_name="principalmodifier")
#
#
#
请记住,还有其他用户类型是有关通过外国键,例如:-
class Administrator(models.Model):
#
#
#
principal = models.ForeignKey(Principal, help_text="The supervising principal for this Administrator")
user = models.OneToOneField(User, blank=True)
province = models.ForeignKey( Province)
landline = models.CharField(blank=True, max_length=20)
mobile = models.CharField(blank=True, max_length=20)
created_by = models.ForeignKey(User, editable=False, blank=True, related_name="administratorcreator")
modified_by = models.ForeignKey(User, editable=False, blank=True, related_name="administratormodifier")
我知道,决不会用一对一的关系对于多表继承在幕后。我只是不合格的足够决定哪一个更健全的方法。
解决方案
我想由@thornomad溶液膨胀。
直接扩展Django的用户类会引起各种麻烦与内部django.auth机制。我已经在类似情况下所做的正是@thornomad暗示 - 我做我自己的用户配置模型挂一到一个与Django的用户模型,我在其中持有额外的用户数据,并从中我继承模型对不同类型的用户。
东西,以适应你所描述的:
class UserProfile(models.Model):
user = models.OneToOneField(User, blank=True, related_name='profile')
class Meta:
abstract = True
class PositionHolderUserProfile(UserProfile):
first_name = models.CharField(max_length=30)
last_name = models.CharField(max_length=30)
landline = models.CharField(blank=True, max_length=20)
mobile = models.CharField(blank=True, max_length=20)
created_by = models.ForeignKey(PositionHolderUserProfile, editable=False, blank=True, related_name="created_users")
modified_by = models.ForeignKey(PositionHolderUserProfile, editable=False, blank=True, related_name="modified_users")
class Principal(PositionHolderUserProfile):
branchoffice = models.ForeignKey(BranchOffice)
class Administrator(PositionHolderUserProfile):
superior = models.ForeignKey(Principal, related_name="subordinates")
province = models.ForeignKey(Province)
class Coordinator(PositionHolderUserProfile):
superior = models.ForeignKey(Administrator, related_name="subordinates")
class Company(UserProfile):
name = models.CharField(max_length=50)
class Product(models.Model):
name = models.CharField(max_length=50)
produced_by = models.ForeignKey(Company)
class Buyer(UserProfile):
first_name = models.CharField(max_length=30)
last_name = models.CharField(max_length=30)
products_bought = models.ManyToManyField(Product)
其他提示
最近,我切换到使用模型的继承的普.汽车。模型。用户。我的一般看法是,在理论他们是伟大的,但有时他们没有得到自动奇迹般地处理像他们应该。
我认为你的决定关于继承与OneToOne下来到这个:
- 我想有Django自动做正确的事情95%的时间,并需要调试,其他5%
-或者-
- 做我想要做的事手我自己100%的时间
如果你还没有见过它,巴勒姆*斯科特博客有一大篇关于继承的用户,并且还建立一个自定义的后端,以确保您的定义对象是正在返回的-- 延伸Django户.
此外,感兴趣的将是AutoOneToOne领域提供的 django-烦人.它是一种混合两种方法在这里-没有继承权,但Django是照顾建立匹配的OneToOneField如果不存在。
此外, thornomad 做一个好点有关的冗余在你的模型。你可以很容易地实行一个抽象的类清洁,为使(假设你在做手册OneToOne):
class BaseExtendedUser(models.Model):
user = models.OneToOneField(User, blank=True, related_name='profile')
landline = models.CharField(blank=True, max_length=20)
mobile = models.CharField(blank=True, max_length=20)
created_by = models.ForeignKey(User, editable=False, blank=True, related_name="created_users")
modified_by = models.ForeignKey(User, editable=False, blank=True, related_name="modified_users")
class Meta:
abstract = True
class Administrator(BaseExtendedUser):
province = models.ForeignKey(Province)
class Principal(BaseExtendedUser):
branchoffice = models.ForeignKey(BranchOffice)
我不认为我会继承User
模型,而使用自定义UserProfile
- 独自离开contrib.auth
模型。通过自定义UserProfile
模型,你可以设置一个的基的用户配置模式,可以是所有的不同用户类型的一部分。
只是看着它快速,太,我会仔细看那个重复所有相同的字段(如您的最后两个Principle
和Administrator
型号)的任何车型。结合内置的与用户配置文件的想法组功能可能你在找什么。
请考虑当协调员被晋升为首席数据模型中会发生什么。在这种情况下,在所有我不会使用继承。请重新考虑以前的海报的建议“结合内置的与用户配置文件的想法组功能可能你在找什么。”
你需要你的用户类的对象表现得像一个auth.User地方?这将是最明显的原因使用继承了OneToOne。一个亲OneToOne做法是在其中您可以通过切换到另一个用户模式的难易程度,如果这是一个问题。
在实际的问题,我看到你有什么上述(无论使用何种方法)是,有没有出现任何东西阻止你有一个主要目的和管理员对象共享相同的用户。 OneToOneField只能保证任何两个之间的关系的一对一的映射。