我有更多的概念性问题,但具有实际意义。
在Django 4.1中。x应用程序,我有一个owner
类,可以是person
或organization
,但从来没有在一起。
这两个类不需要在数据库中注册,只有owner
必须注册:
from django.db import models
class Person(models.Model):
first_name = models.CharField(
max_length=256,
verbose_name=_("First name"),
null=False,
)
# other person attributes, e.g.:
surname = models.CharField(
max_length=256,
verbose_name=_("Surname"),
null=False,
)
street = models.CharField(
max_length=256,
verbose_name=_("Street"),
null=False,
)
country = models.CharField(
max_length=256,
verbose_name=_("Country"),
null=False,
)
class Meta:
abstract = True
def __str__(self):
return self.first_name
class Organization(models.Model):
full_name = models.CharField(
max_length=256,
verbose_name=_("Full name"),
null=False,
)
# other organization attributes, e.g.:
register_identifier = models.CharField(
max_length=64,
verbose_name=_("Register identifier"),
null=False,
)
street = models.CharField(
max_length=256,
verbose_name=_("Street"),
null=False,
)
country = models.CharField(
max_length=256,
verbose_name=_("Country"),
null=False,
)
class Meta:
abstract = True
def __str__(self):
return self.full_name
无论owner
实例是什么,它必须有一个name
属性:
对于个人,所有者的名称必须是first_name
,对于组织,所有者的名称必须是full_name
。
同样,如果owner
对象是Person
的实例:我只想公开Person
的其他属性。同样,如果owner
是Organization
的实例。
我在这里肯定错过了一些概念/也许我没有朝正确的方向看,但是如何基于"条件或参数化继承"类型构建owner
模型?
请注意,Person
类也用于构建其他对象,例如整个应用程序中的designer
或painter
。Organization
也是如此,它作为不同类型组织的基础。因此他们的abstract = True
。
编辑
正如SamSparx在下面的评论中建议的那样,我尝试使用吸引人的"代理"。的概念。为此,我需要从Person
和Organization
类中删除abstract = True
标志,并在Owner
类中设置proxy = True
。但是,当尝试makemigrations
时,它说:
TypeError: Proxy model 'Owner' has more than one non-abstract model base class.
class Owner(Organisation, Person):
class Meta:
proxy = True
这是预期的文档说:基类限制
代理模型必须完全继承一个非抽象模型类。您不能从多个非抽象模型中继承,因为代理模型不提供不同数据库表中的行之间的任何连接。代理模型可以继承任意数量的抽象模型类,只要它们不定义任何模型字段。代理模型也可以继承任意数量的代理模型,这些代理模型共享一个公共的非抽象父类。
来源:https://docs.djangoproject.com/en/4.1/topics/db/models/base-class-restrictions
所以它目前没有真正的帮助。
有几种可能的方法,但它们都有权衡。这在很大程度上取决于所有类都使用同一个表的重要性。根据经验,如果一个非抽象模型需要新的字段,它就需要一个新的表。
抽象类:
这些作为原型是有用的,但你不能把它们组合起来,然后只有一个抽象类"活动"。如果Org和Person都是用来创建Owner的抽象类,那么Owner将拥有这两个类中的所有字段。
任何非抽象类都需要自己的表,例如Owner的子类或其他具有Person抽象的类。
代理类:
这基本上是只使用一个表的选项。使用这个方法,你可以使用同一个表为你的类和它的子类创建单独的子类,每个类都有不同的方法和属性。但是,它们都必须共享相同的字段。如果只是偶尔需要新字段,则可以将它们添加到基类中,而不需要太多的开销,并通过相应的代理类的方法处理或忽略它们。