具有相同或相似字段的Django模型

1 投票
2 回答
1455 浏览
提问于 2025-04-18 06:54

我开始学习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 个回答

0

是的,确实有区别,你刚刚贴的链接是文档,里面解释了这个区别。

Restaurant 数据库表在(2)中包含了两个额外的字段(serves_hot_dogsserves_pizza),还有一个指向 Place 数据库表的外键。

关于你该使用哪个模型的问题——选择最适合你的那个。我通常在类似情况下使用多表继承。

在深入了解表继承之前,请先看看这个链接:https://django-model-utils.readthedocs.org/en/latest/managers.html#inheritancemanager。我用它来减少处理多表继承时的查询次数。

1

在这种情况下,我觉得你应该使用继承(方案2)。

因为Restaurant(餐厅)是一个特殊的Place(地方),这意味着餐厅有name(名字)和address(地址)这两个属性。此外,餐厅还有serves_hot_dogs(提供热狗)和serves_pizza(提供披萨)这两个属性。

考虑到以上描述,所有的方案都是合理的。但是,Restaurant是一个Place,所以餐厅必须能够被当作地方来处理。在方案1中,RestaurantPlace是分开的,你不能把Restaurant当作Place来处理。(仅从面向对象编程的角度考虑)

另一方面,在方案1中,如果我保存一个地址为A的Place,然后我再添加一个地址相同的Restaurant,那么我就会在数据库中保存两个相同的地址,这样会导致冗余和不一致。


这个问题和面向对象编程中组合和继承的区别是类似的。

撰写回答