我有一个概念性的问题,但有实际意义。
在Django 4.1.x应用中,我有一个owner
类,它可以是person
或organization
,但不能同时是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
时,它说:
第一次
这是预期的,正如医生所说:基底类别限制
代理模型只能继承一个非抽象模型类。不能继承多个非抽象模型,因为代理模型不提供不同数据库表中的行之间的任何连接。代理模型可以继承任意数量的抽象模型类。代理模型也可以从共享公共非抽象父类的任意数量的代理模型继承。
来源:https://docs.djangoproject.com/en/4.1/topics/db/models/#base-class-restrictions
所以现在也没什么用。
1条答案
按热度按时间68bkxrlz1#
有几种可能的方法,但它们都有折衷。这在很大程度上取决于你的类都使用同一个表的重要性。作为经验法则,如果一个非抽象模型需要新的字段,它就需要一个新的表。
抽象类:
这两个类作为原型很有用,但是你不能把它们组合起来,这样就只有一个抽象类“active”。如果Org和Person都是用来创建Owner的抽象类,那么Owner将拥有这两个类中的所有字段。
任何非抽象类都需要自己的表,例如,Owner的子类或其他具有Person抽象的类。
代理类:
这基本上是您只使用一个表的选择。使用这种方法,您可以为您的类创建单独的子类,并且它的所有子类都使用同一个表,每个类都有不同的方法和属性。但是,它们必须共享相同的字段。如果只是偶尔子类需要新字段,则可以将它们添加到基类中,而不需要太多的开销。并通过相应的代理类的方法处理或忽略。