哪个更好:外键或模型继承?

wha*_*atf 8 django django-models

我有这个用例场景:有些地方是游乐场,餐馆,剧院,酒吧.同样place可以有游乐场,餐馆,剧院等.有几种方法可以实现它:

  1. 使用外键

    class Place(models.Model):
        name = models.CharField(max_length=50)
    
    class PlayGrounds(models.Model)
        field1 = models.CharField(max_length=50)
        place = models.ForeignKey(Place)
    
    Run Code Online (Sandbox Code Playgroud)
  2. 多元遗传

    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()
    
    Run Code Online (Sandbox Code Playgroud)
  3. 使用抽象类

    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
    
    Run Code Online (Sandbox Code Playgroud)
  4. 使用代理模型

    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
    
    Run Code Online (Sandbox Code Playgroud)

使用每种方法的利弊是什么?

Chr*_*att 15

第一个基本模型继承,因为这是Django的实现MTI的使用(除非它是一个OneToOneField替代的ForeignKey,但是这仅仅是ForeignKey这是唯一的).

任何时候你都有一个is-a关系(即,一个餐馆就是一个地方),你正在处理继承,所以使用Django的模型继承方法之一就是要走的路.然而,每个都有其优点和缺点:

抽象模型

当您只想卸载重复的字段和/或方法时,抽象模型很有用.他们最好用作mixins,而不仅仅是真正的"父母".例如,所有这些模型都有一个地址,因此创建一个抽象Address模型并从中继承每个模型可能是一个有用的东西.但是,a 本身Restaurant并不是一个Address,所以这不是一个真正的亲子关系.

MTI(多表继承)

这是与您上面的第一选择类似的那个.当您需要与父类和子类进行交互并且子项具有自己的唯一字段(字段,而不是方法)时,这非常有用.所以Restaurant可能有一个cuisine领域,但Place不需要.但是,它们都有一个地址,所以Restaurant继承和构建Place.

代理模型

代理模型就像别名.他们不能拥有自己的领域,只能获得父级的领域.但是,它们可以有自己的方法,因此当您需要区分相同的东西时,这些方法很有用.例如,我可能会创建类似StaffUserNormalUser来自的代理模型User.仍然只有一个用户表,但我现在可以为每个用户表添加唯一的方法,创建两个不同的管理员视图等.

对于您的方案,代理模型没有多大意义.孩子天生就比母公司更复杂,这是没有意义的存储所有喜欢的领域cuisineRestaurantPlace.

可以使用抽象Place模型,但是你失去了实际工作的能力Place.当你想要一个外键到一个通用的"地方"时,你将不得不使用通用的外键,而是能够从不同的地方类型中进行选择,如果没有必要,会增加很多开销.

你最好的选择是使用正常继承:MTI.然后,您可以创建一个外键Place并添加任何子项Place.