Django中模型的繼承與Python普通類的繼承一樣亚铁,不過基類要是django.db.models.Model
在Django中有三種繼承的方式
- 僅僅想用父類保存一下不是每個(gè)子類都鍵入的信息蝇刀,抽象class是很好的選擇
- 繼承一個(gè)存在model,并且想讓每個(gè)model都有一個(gè)數(shù)據(jù)表徘溢。多表繼承
- 改變在Python層面上的一些model的行為吞琐,而不是model的字段捆探。
Abstract base classes
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)
>>>abstract=True表明CommonInfo是一個(gè)抽象類,不在數(shù)據(jù)庫中建表站粟,CommonInfo不能直接使用黍图。同時(shí)Student與CommonInfo不能有名稱相同的屬性。Student由于繼承了CommonInfo奴烙,所有Student有三個(gè)字段name,age,home_group助被。如果子類中沒有定義Meta則其繼承父類的Meta。子類也可以擴(kuò)展父類的Meta
class Meta(CommonInfo.Meta): db_table = 'student_info'
小心處理related_name and related_query_name
如果使用related_name和related_query_name使用在外鍵和多對多的關(guān)系中切诀,必須制定一個(gè)唯一的名字恰起。在抽象類中使用related_name和related_query_name需要與app_label和class標(biāo)記
'%(class)s'將會(huì)被子類小寫名,而'%(app_label)s'會(huì)被子類所在的app小寫名替代
common/models.py
from django.db import models
class Base(models.Model):
m2m = models.ManyToManyField(OtherModel,
relate_name="%(app_label)s_%(class)s_related",
related_query_name="%(app_label)s_%(class)ss",)
class Meta:abstract=True
class ChildA(Base):pass
class ChildB(Base):pass
>>>
common.ChildA.m2m的reverse name是common_childa_related
reverse query name是common_childas趾牧。如果不指定related_name則默認(rèn)為子類名+_set, ------>childa_set
Multi-table inheritance
from django.db import models
class Place(models.Model):
name = models.CharField(max_lenght=50)
address = models.CharField(max_length=80)
class Restaurant(Place):
serves_hot_dogs = models.BooleanField(default=False)
serves_pizza = models.BooleanField(default=False)
place_ptr = models.OneToOneField(
Place,
on_delete=models.CASCADE,
parent_link=True,
) #與父類進(jìn)行一對一關(guān)聯(lián)
>>>
這種寫法會(huì)在數(shù)據(jù)庫中創(chuàng)建兩個(gè)表检盼,同時(shí)Restaurant擁有Place所有的字段
>>> Place.objects.filter(name="Bob's Cafe")
>>> Restaurant.objects.filter(name="Bob's Cafe")
>>> p = Place.objects.get(id=12)
# If p is a Restaurant object, this will give the child class: >>> p.restaurant
<Restaurant: ...>
Proxy models
采用Multi-table inheritance的方式需要為每一個(gè)類創(chuàng)建一個(gè)數(shù)據(jù)表,比較耗資源翘单《滞鳎可以采用代理模型,可以對代理模型進(jìn)行數(shù)據(jù)操作哄芜,而反應(yīng)在原始模型上
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
>>> MyPerson和Person會(huì)操作同一個(gè)數(shù)據(jù)表
>>> p = Person.objects.create(first_name="foobar")
>>> MyPerson.objects.get(first_name="foobar")
<MyPerson: foobar>
proxy model必須繼承一個(gè)非抽象model貌亭,proxy model還可以繼承一個(gè)proxy model共享一個(gè)非抽象model。如果沒有為proxy指定一個(gè)manager那么其將繼承父類的manager认臊,如果定義了一個(gè)manager圃庭,那么這個(gè)manger稱謂proxy model的默認(rèn)manager。同時(shí)父類的manager照樣能夠運(yùn)行失晴。