我有这个用例场景:
有些地方是游乐场,餐馆,剧院,酒吧。
相同的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
使用每种方法有哪些优缺点?
答案 0 :(得分:15)
第一个 本质上是模型继承,因为这是Django对MTI的实现所使用的(除了OneToOneField
而不是ForeignKey
,但这只是{{} 1}}这是唯一的。)
只要你有一个 is-a 关系(即,一个餐馆就是一个地方),你就是在处理继承,所以使用Django的模型继承方法之一就是要走的路。然而,每个都有其优点和缺点:
抽象模型
当您只想卸载重复的字段和/或方法时,抽象模型很有用。他们最好用作mixins,而不仅仅是真正的“父母”。例如,所有这些模型都有一个地址,因此创建一个抽象的ForeignKey
模型并从中继承每个模型可能是一个有用的东西。但是,Address
本身不是Restaurant
,所以这不是真正的亲子关系。
MTI(多表继承)
这是与您上面的第一个选择类似的选项。当您需要与父类和子类进行交互并且子项具有自己的唯一字段(字段,而不是方法)时,这非常有用。因此,Address
可能包含Restaurant
字段,但cuisine
不需要该字段。但是,它们都有一个地址,因此Place
继承并构建Restaurant
。
代理模型
代理模型就像别名。他们不能拥有自己的领域,只能获得父级的领域。但是,它们可以有自己的方法,因此当您需要区分相同的东西时,这些方法很有用。例如,我可以从Place
创建代理模型,如StaffUser
和NormalUser
。仍然只有一个用户表,但我现在可以为每个用户表添加独特的方法,创建两个不同的管理员视图等。
对于您的方案,代理模型没有多大意义。这些孩子本质上比父母更复杂,将User
的{{1}}等所有字段存储在cuisine
上是没有意义的。
你可以使用抽象的Restaurant
模型,但是你失去了自己实际工作Place
的能力。当你想要一个外键到一个通用的“地方”时,你将不得不使用通用的外键,而是能够从不同的地方类型中进行选择,如果没有必要,会增加很多开销。
你最好的选择是使用正常继承:MTI。然后,您可以为Place
创建一个外键,并添加Place
的子项。
答案 1 :(得分:1)
这完全取决于您需要什么样的行为。
您是否需要在地方,餐馆或游乐场进行相同的操作? 您是否会检查您的服务(餐馆等)是否在同一个地方?将具有相同地址的两个地方视为不同,并将其相关服务视为不同,这是否有意义?
如果不知道这些问题的答案,就不可能说哪种技巧最合适,因为它们是非常不同的技术,而不是一般的替代技术。
继承的使用不应该由预先设想的关于分类法的概念决定,因为不存在对分类法进行建模的原因:它提供了函数多态性(数据成员继承主要是为了促进这一点)。
答案 2 :(得分:0)
如果域名规定如果place
不是至少其中一个place
,那么我会投票给一个抽象类。
但如果{{1}}不需要任何东西,你需要多次继承才能容纳地方标记(空地)?
我认为专业人士和骗子围绕着你对虚假数据库表的喜爱。 ORM如何实施这些解决方案?就个人而言,我并不喜欢拥有大量的单场表,而是ymmv。
答案 3 :(得分:0)
我会投票给第一个,因为它是最明确的。我没有看到任何其他方法的优点。