我有这样的用例场景:
有些地方是游乐场、餐馆、剧院、酒吧。
相同place
可以有游乐场、餐馆、剧院等。
有几种实现方法:
-
使用外键
class Place(models.Model):
name = models.CharField(max_length=50)
class PlayGrounds(models.Model)
field1 = models.CharField(max_length=50)
place = models.ForeignKey(Place)
-
多表继承
class Place(models.Model):
name = models.CharField(max_length=50)
address = models.CharField(max_length=80)
class Restaurant(Place):
serves_hot_dogs = models.BooleanField()
serves_pizza = models.BooleanField()
-
使用抽象类
class Place(models.Model):
name = models.CharField(max_length=50)
class PlayGrounds(Place)
field1 = models.CharField(max_length=50)
place = models.ForeignKey(Place)
class Meta:
abstract = True
-
使用代理模型
class Place(models.Model):
name = models.CharField(max_length=50)
class PlayGrounds(Place)
field1 = models.CharField(max_length=50)
place = models.ForeignKey(Place)
class Meta:
proxy = True
使用每种方法的优点和缺点是什么?
第一个is本质上是模型继承,因为这就是 Django 的 MTI 实现所使用的(除了它是一个OneToOneField
代替ForeignKey
,但这只是一个ForeignKey
这是独一无二的)。
任何时候你有一个is-a关系(即,餐厅是一个地方),您正在处理继承,因此使用 Django 的模型继承方法之一是最佳选择。然而,每种方法都有其优点和缺点:
抽象模型
当您只想卸载重复的字段和/或方法时,抽象模型非常有用。它们最好用作 mixins,而不是真正的“父母”。例如,所有这些模型都会有一个地址,因此创建一个抽象Address
模型并让每个模型继承它可能是一件有用的事情。但是,一个Restaurant
不是一个Address
,本身,所以这不是真正的亲子关系。
MTI(多表继承)
这与您上面的第一个选择类似。当您需要与父类和子类交互并且子类拥有自己的独特字段(字段,而不是方法)时,这是最有用的。所以一个Restaurant
可能有一个cuisine
场,但是一个Place
不需要那个。然而,他们都有一个地址,所以Restaurant
继承并构建Place
.
代理模型
代理模型就像别名。他们不能拥有自己的字段,他们只能获得父级的字段。但是,它们可以有自己的方法,因此当您需要区分同一事物的种类时,这些方法非常有用。例如,我可能会创建像这样的代理模型StaffUser
and NormalUser
from User
。仍然只有一个用户表,但我现在可以为每个表添加独特的方法,创建两个不同的管理视图等。
对于您的场景,代理模型没有多大意义。孩子本质上比父母更复杂,存储像这样的所有字段是没有意义的cuisine
for Restaurant
on Place
.
You could使用摘要Place
模型,但随后你就失去了实际工作的能力Place
在其自己的。当您想要通用“地点”的外键时,您必须使用通用外键,以便能够从不同的地点类型中进行选择,如果没有必要,这会增加大量开销。
最好的选择是使用正常继承:MTI。然后您可以创建一个外键Place
并添加任何子项Place
.
本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)