Django 外键和模型继承哪个更好?
我有这个用例场景: 有些地方要么是游乐场,要么是餐馆,要么是剧院,要么是酒吧。 同一个Django 外键和模型继承哪个更好?,django,django-models,Django,Django Models,我有这个用例场景: 有些地方要么是游乐场,要么是餐馆,要么是剧院,要么是酒吧。 同一个地方可以有操场、餐厅、剧院等。 有两种实现方法: 使用外键 class Place(models.Model): name = models.CharField(max_length=50) class PlayGrounds(models.Model) field1 = models.CharField(max_length=50) place = models.ForeignKey
地方
可以有操场、餐厅、剧院等。
有两种实现方法:
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
使用每种方法的优缺点是什么?如果域规定一个
位置如果不是其他位置中的至少一个就不可能存在,我会投票选择一个抽象类
但是,如果一个场所
不需要任何东西,你就需要多重继承来容纳场所标记(空地)
我想赞成和反对的观点都是围绕着你对虚假数据库表的喜爱而展开的。ORM如何实现这些解决方案?就我个人而言,我不喜欢有很多单字段表,但我喜欢ymmv。我会投票支持第一个,因为它是最明确的。我看不到任何其他方法的建议。这完全取决于你需要什么样的行为
您是否需要在场所、餐厅或游乐场执行相同类型的操作?
您是否会检查您的服务(餐厅等)是否在同一地点?将两个地址相同的地方视为不同的地方,并将其相关服务视为不同的地方,是否有意义
如果不知道这类问题的答案,就不可能说哪一种是最合适的技巧,因为它们是非常不同的技巧,通常不会相互替代。
继承的使用不应受到预先设想的分类概念的支配,因为它不是为分类建模的:它是为了提供函数多态性(数据成员继承主要是为了促进这一点) 第一个基本上是模型继承,因为Django的MTI实现就是这样使用的(除了它是一个OneToOneField
而不是ForeignKey
,但这只是一个独特的ForeignKey
)
只要你有一个is-a关系(即,餐厅就是一个地方),你就在处理继承问题,因此使用Django的模型继承方法之一就是一条出路。然而,每种方法都有其优缺点:
抽象模型
当您只想卸载重复的字段和/或方法时,抽象模型非常有用。它们最适合作为调味品,而不是真正的“父母”。例如,所有这些模型都有一个地址,因此创建一个抽象的地址模型并从中继承可能是一件有用的事情。但是,餐厅
本身不是地址
,因此这不是真正的亲子关系
MTI(多表继承)
这是一个类似于你的第一选择上面。当您需要与父类和子类进行交互,并且子类具有自己的唯一字段(字段,而不是方法)时,这非常有用。因此,餐厅
可能有一个烹饪
字段,但场所
不需要这个字段。但是,它们都有一个地址,因此餐厅
继承并构建了场所
代理模型
代理模型类似于别名。它们不能有自己的字段,只能获取父级的字段。但是,它们可以有自己的方法,所以当您需要区分同一事物的种类时,这些方法非常有用。例如,我可以从User
创建代理模型,如StaffUser
和NormalUser
。仍然只有一个用户表,但我现在可以为每个表添加唯一的方法,创建两个不同的管理视图,等等
对于您的场景,代理模型没有多大意义。孩子们天生就比父母更复杂,所以在Place
上存储餐厅的等所有字段是没有意义的
您可以使用抽象的Place
模型,但这样您就失去了实际独立工作Place
的能力。当您想要一个外键指向一个通用的“位置”时,您必须使用通用外键,以便能够从不同的位置类型中进行选择,如果不需要的话,这会增加很多开销
最好的选择是使用普通继承:MTI。然后,您可以为Place
创建一个外键,并添加Place
的子对象。在我们帮助您之前,您需要告诉我们更多关于这些对象和类的操作。如果您仔细研究一下,我只想问在哪个位置首选哪种实现方法?这更像是一个建筑问题。“建筑”问题不能抽象地回答。不知何故,我一直喜欢你的答案,这也不例外。谢谢哈,我也是!不知怎的,我想克里斯其实知道他在做什么。哇,我喜欢这个答案。我有一个相关的问题,如果你有时间,也许可以在这里回答?非常感谢!