多表继承

使用这种继承方式时,每一个层级下的每个 model 都是一个真正意义上完整的 model 。 每个 model 都有专属的数据表,都可以查询和创建数据表。 继承关系在子 model 和它的每个父类之间都添加一个链接 (通过一个自动创建的隐含的 OneToOneField 来实现)。

例如:

from django.db import models

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

# 继承自Place
class Restaurant(Place):
    serves_hot_dogs = models.BooleanField(default=False)
    serves_pizza = models.BooleanField(default=False)

Restaurant 现在除了拥有 serves_hot_dogs、serves_pizza,两个字段外,还拥有继承得来的 name 、address 两字段。所以下面两个语句都是可以运行的:

Place.objects.filter(name="辉记糖水")
Restaurant.objects.filter(name="辉记糖水")

如果有一个 Place ,它同时也是一个 Restaurant, 那么你可以使用 model 的小写形式从 Place 对象中获得与其对应的 Restaurant对象:

>>> p = Place.objects.get(name="辉记糖水")
>>> p.restaurant

但是,如果上例中的 p 并不是 Restaurant (比如它仅仅只是 Place 对象,或者它是其他类的父类),那么在引用 p.restaurant 就会抛出Restaurant.DoesNotExist 异常。





继承与反向关联

因为多表继承使用了一个隐含的 OneToOneField 来链接子类与父类,但是这个 OnetoOneField 字段默认的 related_name 值与 ForeignKey 和 ManyToManyField 默认的反向名称相同。

当一个子类含有多对一或是多对多关系,你就必须在每个多对一和多对多字段上强制指定 related_name。如果你没这么做,Django 就会在你运行验证(validation) 时抛出异常。

例如,仍以上面 Place类为例,我们创建一个带有 ManyToManyField字段的子类:

class Supplier(Place):
    customers = models.ManyToManyField(Place)

这会产生一个错误:

Reverse query name for 'Supplier.customers' clashes with reverse query
name for 'Supplier.place_ptr'.

HINT: Add or change a related_name argument to the definition for
'Supplier.customers' or 'Supplier.place_ptr'.

要解决这个问题,要向 customers 字段中添加 related_name :

class Supplier(Place):
    customers = models.ManyToManyField(Place, related_name='provider')

要查询 Supplier 时就可以用 provider 来调用:

>>> p = Place.objects.get(name='辉记糖水')

# 查找辉记糖水的供应商
>>> p.provider.all()
]>

你可能感兴趣的:(多表继承)