哪个更好:外键或模型继承? [英] Which is better: Foreign Keys or Model Inheritance?

查看:95
本文介绍了哪个更好:外键或模型继承?的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我有这个用例情况:
有地方是游乐场,餐馆,剧院,酒吧。
相同的地方可以有游乐场,餐馆,剧院等。
有几种方法来实现:


  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)


  2. 多重继承

      class Place(models.Model):
    name = models.CharField(max_length = 50)
    address = models.CharField(max_length = 80 )

    class餐厅(Place):
    serve_hot_dogs = models.BooleanField()
    serving_pizza = models.BooleanField()
    pre>

  3. 使用抽象类

      class Place .Model):
    name = models.CharField(max_length = 50)

    class PlayGrounds(Place)
    field1 = models.CharField(max_leng th = 50)
    place = models.ForeignKey(Place)
    class Meta:
    abstract = True

    li>

  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


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

解决方案

第一个基本上是模型继承,因为这就是Django的MTI实现使用(除了它是一个 OneToOneField 而不是一个 ForeignKey 但这只是一个 ForeignKey ,这是唯一的)。



只要你有一个 is-a 关系(即一个餐厅是一个地方),你正在处理继承,所以使用一个Djan go的模式继承方法是要走的路。然而,每个都有其优点和缺点:



抽象模型



摘要当您只想卸载重复的字段和/或方法时,模型很有用。他们最适合用作mixins,而不是真正的父母。例如,所有这些模型都将有一个地址,所以创建一个抽象的地址模型,并且每个模型都继承自它可能是一件有用的事情。但是,餐厅本身并不是一个地址,所以这不是一个真正的亲子关系。 / p>

MTI(多表继承)



这是一个类似于上面的第一选择。当您需要与父类和子类进行交互时,这是最有用的,而且子类具有自己的唯一字段(字段,而不是方法)。因此,餐厅可能会有一个美食字段,但是 Place 不需要但是,他们都有一个地址,所以餐厅继承并建立了 Place

$ b $代理模型



代理模型与别名一样。他们不能拥有自己的领域,他们只得到父母的领域。但是,他们可以有自己的方法,所以当你需要区分同样的东西时,这些方法是有用的。例如,我可以从用户 StaffUser NormalUser $ C>。仍然只有一个用户表,但我现在可以为每个用户添加唯一的方法,创建两个不同的管理视图等。



对于您的方案,代理模型不会很有意义孩子本身比父母更复杂,把美食之类的所有字段存储在餐厅 Place



您可以使用抽象的放置模型,但是您将失去实际工作的能力, Place 。当你想要一个普通的地方的外键时,你必须使用通用的外键,而不是在不同的地方类型之间进行选择,如果没有必要的话会增加很多开销。



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


I have this use case scenario: there are places which are either playgrounds, restaurants, theatres, pubs. the same place can have playgrounds, restaurants, theatres etc. there are couple of ways of implementing it:

  1. use foreign keys

    class Place(models.Model):
        name = models.CharField(max_length=50)
    
    class PlayGrounds(models.Model)
        field1 = models.CharField(max_length=50)
        place = models.ForeignKey(Place)
    

  2. multitable inheritance

    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()
    

  3. use abstract class

    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
    

  4. use proxy models

    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
    

What are the pros and cons of using each approach?

解决方案

The first one is essentially model inheritance, because that's what Django's implementation of MTI uses (except it's a OneToOneField instead of a ForeignKey, but that's merely a ForeignKey that's unique).

Anytime you have an is-a relationship (i.e., a Restaurant is a Place), you're dealing with inheritance, so using one of Django's model inheritance methodologies is the way to go. Each, however, has its pros and cons:

Abstract Models

Abstract models are useful when you just want to off-load repetitive fields and/or methods. They're best used as mixins, more than true "parents". For example, all of these models will have an address, so creating an abstract Address model and having each inherit from that might be a useful thing. But, a Restaurant is not an Address, per se, so this is not a true parent-child relationship.

MTI (Multiple Table Inheritance)

This is the one that's akin to your first choice above. This is most useful when you need to interact with both the parent and child classes and the children have unique fields of their own (fields, not methods). So a Restaurant might have a cuisine field, but a Place wouldn't need that. However, they both have an address, so Restaurant inherits and builds off of Place.

Proxy Models

Proxy models are like aliases. They cannot have their own fields, they only get the fields of the parent. However, they can have their own methods, so these are useful when you need to differentiate kinds of the same thing. For example, I might create proxy models like StaffUser and NormalUser from User. There's still only one user table, but I can now add unique methods to each, create two different admin views, etc.

For your scenario, proxy models don't make much sense. The children are inherently more complicated than the parent and it wouldn't make sense to store all the fields like cuisine for Restaurant on Place.

You could use an abstract Place model, but then you lose the ability to actually work Place on its own. When you want a foreign key to a generalized "place", you'll have to use generic foreign keys, instead, to be able to choose from among the different place types, and that adds a lot of overhead, if it's not necessary.

Your best bet is using normal inheritance: MTI. You can then create a foreign key to Place and add anything that is a child of Place.

这篇关于哪个更好:外键或模型继承?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆