使用這種繼承方式時,每一個層級下的每個 model 都是一個真正意義上完整的 model 。 每個 model 都有專屬的數(shù)據(jù)表,都可以查詢和創(chuàng)建數(shù)據(jù)表。 繼承關系在子 model 和它的每個父類之間都添加一個鏈接 (通過一個自動創(chuàng)建的隱含的 OneToOneField 來實現(xiàn))。
例如:
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 現(xiàn)在除了擁有 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
<Restaurant: 輝記糖水>
但是,如果上例中的 p 并不是 Restaurant (比如它僅僅只是 Place 對象,或者它是其他類的父類),那么在引用 p.restaurant 就會拋出Restaurant.DoesNotExist 異常。
繼承與反向關聯(lián)
因為多表繼承使用了一個隱含的 OneToOneField 來鏈接子類與父類,但是這個 OnetoOneField 字段默認的 related_name 值與 ForeignKey 和 ManyToManyField 默認的反向名稱相同。
當一個子類含有多對一或是多對多關系,你就必須在每個多對一和多對多字段上強制指定 related_name。如果你沒這么做,Django 就會在你運行驗證(validation) 時拋出異常。
例如,仍以上面 Place類為例,我們創(chuàng)建一個帶有 ManyToManyField字段的子類:
class Supplier(Place):
customers = models.ManyToManyField(Place)
這會產(chǎn)生一個錯誤:
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 來調(diào)用:
>>> p = Place.objects.get(name='輝記糖水')
# 查找輝記糖水的供應商
>>> p.provider.all()
<QuerySet [<Supplier: 糖廠>]>