- Django 的所有基類都必須是
django.db.models.Model的子類 - Djang 共有三種繼承方式:
(1) 抽象基類:基類不會(huì)被單獨(dú)使用(模型不會(huì)用于創(chuàng)建任何數(shù)據(jù)庫(kù)表),用于保存子模型的一些公共信息
(2) 多表繼承:子類化一個(gè)現(xiàn)有模型(可能完全來(lái)自另一個(gè)應(yīng)用程序),但每個(gè)模型都有自己的數(shù)據(jù)庫(kù)表
(3) 代理模型:僅修改模型的Python級(jí)行為,而不以任何方式更改模型字段
抽象基類
??抽象基類聲明:像普通模型一樣聲明,但需要在Meta類中設(shè)置abstract=True
from django.db import models
class CommonInfo(models.Model):
name = models.CharField(max_length=100)
age = models.PositiveIntegerField()
# 聲明抽象基類
class Meta:
abstract = True
class Student(CommonInfo):
home_group = models.CharField(max_length=5)
??當(dāng)進(jìn)行數(shù)據(jù)庫(kù)遷移的時(shí)候,由于CommonInfo類聲明是抽象基類,所以不會(huì)生成數(shù)據(jù)庫(kù)表或具有管理器,并且無(wú)法直接實(shí)例化或保存。
??由于 Student 類繼承 CommonInfo 類,所以 Student 生成的數(shù)據(jù)庫(kù)為Student(name, age, home_group )
Meta 繼承
- 當(dāng)使用抽象基類時(shí),如果子類沒(méi)有聲明它自己的Meta類,它將繼承父類的Meta。
- 如果子類想要擴(kuò)展父類的Meta類,可以將其子類化。
- 當(dāng)子類繼承父類Meta時(shí),會(huì)自動(dòng)設(shè)置
abstract=False,即抽象基類的子項(xiàng)本身不會(huì)自動(dòng)成為抽象類,如果想聲明抽象基類,必須在自己的Meta中聲明abstract=True
from django.db import models
class CommonInfo(models.Model):
name = models.CharField(max_length=100)
age = models.PositiveIntegerField()
# 聲明抽象基類
class Meta:
abstract = True
ordering = ['name']
class Student(CommonInfo):
home_group = models.CharField(max_length=5)
# 繼承CommonInfo類的Meta
class Meta(CommonInfo.Meta):
db_table = 'student_info'
- 在抽象基類Meta類中包含一些屬性是無(wú)意義的,比如說(shuō)如果在抽象基類中包含
db_table則意味著所有子類將使用相同的數(shù)據(jù)庫(kù)表
多表繼承
??每個(gè)模型對(duì)應(yīng)于自己的數(shù)據(jù)庫(kù)表,可以單獨(dú)查詢和創(chuàng)建。多表繼承使得子模型與父模型之間創(chuàng)建一對(duì)一關(guān)系OneToOneField
from django.db import models
class Place(models.Model):
name = models.CharField(max_length=50)
address = models.CharField(max_length=80)
class Restaurant(Place):
serves_hot_dogs = models.BooleanField(default=False)
serves_pizza = models.BooleanField(default=False)
其中Restaurant類等價(jià)于
class Restaurant(models.Model):
place_ptr = models.OneToOneField(
Place,
on_delete=models.CASCADE,
parent_link=True,
)
serves_hot_dogs = models.BooleanField(default=False)
serves_pizza = models.BooleanField(default=False)
Meta與多表繼承
- 一般情況下,子類無(wú)法繼承父類Meta
- 在少數(shù)有限的情況下,子類從父類繼承行為:如果子類沒(méi)有指定
ordering屬性或get_latest_by屬性,那么它將從父元素繼承這些屬性。 - 如果父級(jí)有一個(gè)排序,并且您不希望子級(jí)具有該排序,則可以使用如
ordering = []明確禁用父類屬性
代理模型
- 作用:為原始模型創(chuàng)建代理。代理可以創(chuàng)建、刪除和更新代理模型的實(shí)例,所有數(shù)據(jù)都將像使用原始(非代理)模型一樣保存。不同之處在于,代理可以更改諸如代理中的默認(rèn)模型排序或默認(rèn)管理器之類的內(nèi)容,而無(wú)需更改原始的排序。
- 代理模型聲明:像普通模型一樣聲明,但需要在Meta類中設(shè)置
proxy=True
from django.db import models
class Person(models.Model):
first_name = models.CharField(max_length=30)
last_name = models.CharField(max_length=30)
class MyPerson(Person):
class Meta:
proxy = True
def do_something(self):
# ...
pass
- 代理的意義:僅修改模型的Python級(jí)行為,而不以任何方式更改模型字段