多表繼承

使用這種繼承方式時,每一個層級下的每個 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: 糖廠>]>
最后編輯于
?著作權歸作者所有,轉載或內(nèi)容合作請聯(lián)系作者
【社區(qū)內(nèi)容提示】社區(qū)部分內(nèi)容疑似由AI輔助生成,瀏覽時請結合常識與多方信息審慎甄別。
平臺聲明:文章內(nèi)容(如有圖片或視頻亦包括在內(nèi))由作者上傳并發(fā)布,文章內(nèi)容僅代表作者本人觀點,簡書系信息發(fā)布平臺,僅提供信息存儲服務。

相關閱讀更多精彩內(nèi)容

友情鏈接更多精彩內(nèi)容