具有相同或相似字段的Django模型
我开始学习Django,已经有一个问题了:如果表格有相似的字段,创建模型的方式哪种更好呢?
1) 就像官方教程里那样的标准方式:
class Place(models.Model):
name = models.CharField(max_length=50)
address = models.CharField(max_length=80)
class Restaurant(models.Model):
name = models.CharField(max_length=50)
address = models.CharField(max_length=80)
serves_hot_dogs = models.BooleanField()
serves_pizza = models.BooleanField()
如你所见,这两个模型都有相同的名字和地址字段。我在这个链接上发现了多表继承,它的工作方式是这样的:
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()
正如文档所说:Place的所有字段在Restaurant中也可以使用,尽管数据会存储在不同的数据库表中。
那么,这两者之间有什么原则上的区别吗?我应该使用哪一种呢?
2 个回答
是的,确实有区别,你刚刚贴的链接是文档,里面解释了这个区别。
Restaurant
数据库表在(2)中包含了两个额外的字段(serves_hot_dogs
和 serves_pizza
),还有一个指向 Place
数据库表的外键。
关于你该使用哪个模型的问题——选择最适合你的那个。我通常在类似情况下使用多表继承。
在深入了解表继承之前,请先看看这个链接:https://django-model-utils.readthedocs.org/en/latest/managers.html#inheritancemanager。我用它来减少处理多表继承时的查询次数。
在这种情况下,我觉得你应该使用继承(方案2)。
因为Restaurant
(餐厅)是一个特殊的Place
(地方),这意味着餐厅有name
(名字)和address
(地址)这两个属性。此外,餐厅还有serves_hot_dogs
(提供热狗)和serves_pizza
(提供披萨)这两个属性。
考虑到以上描述,所有的方案都是合理的。但是,Restaurant
是一个Place
,所以餐厅必须能够被当作地方来处理。在方案1中,Restaurant
和Place
是分开的,你不能把Restaurant
当作Place
来处理。(仅从面向对象编程的角度考虑)
另一方面,在方案1中,如果我保存一个地址为A的Place
,然后我再添加一个地址相同的Restaurant
,那么我就会在数据库中保存两个相同的地址,这样会导致冗余和不一致。
这个问题和面向对象编程中组合和继承的区别是类似的。