Django中Model的繼承有三種:
1、抽象繼承
2、多表繼承
3、proxy model(代理model)
1、抽象繼承
第一種抽象繼承,創建一個通用父類,爲了使父類不會被創建,在抽象父類的Meta中設置abstract=True就可以。子類會繼承父類相同的字段.
子類模型Student就會有s_name, s_age, s_sex三個字段
class CommonInfo(models.Model):
s_name = models.CharField(max_length=32)
s_age = models.PositiveIntegerField(default=22)
class Meta:
abstract = True
class Student(CommonInfo):
home_group = models.CharField(max_length=32)
對於內聯的Meta類的繼承,一般的,父類的Meta類的屬性會繼承給子類,子類也可以在自己的Meta中重寫或者拓展父類的Meta,拓展的話主要是繼承父類的Meta:
class CommonInfo(models.Model):
...
class Meta:
abstract = True
ordering = ['name']
class Student(CommonInfo):
...
class Meta(CommonInfo.Meta):
db_table = 'student_info'
繼承時,Django 會對基類的 Meta 內嵌類做一個調整:在安裝 Meta 屬性之前,Django 會設置 abstract=False。 這意味着抽象基類的子類不會自動變成抽象類。當然,你可以讓一個抽象類繼承另一個抽象基類,不過每次都要顯式地設置 abstract=True 。
對於抽象基類而言,有些屬性放在 Meta 內嵌類裏面是沒有意義的。例如,包含 db_table 將意味着所有的子類(是指那些沒有指定自己的 Meta 內嵌類的子類)都使用同一張數據庫表,一般來說,這並不是我們想要的。
2,多表繼承
第二種多表繼承,其中父類也是一個Django模型,並且會創建一個數據表,多表繼承是Django中隱式的一對一關係:
class Place(models.Model):
name = models.CharField(max_length=50)
address = models.CharField(max_length=80)
class Restaurant(Place):
serves_hot_dogs = models.BooleanField()
serves_pizza = models.BooleanField()
這裏,MyPerson沒有多創建數據表,MyPerson也是對Person的數據表進行操作,一般的,我們可以把MyPerson當做Person來使用,只是在do_something這個方法略有不同,比如
>>> p = Person.objects.create(first_name="foobar")
>>> MyPerson.objects.get(first_name="foobar")
<MyPerson: foobar>
代理模型和原模型的區別如下面:
class OrderedPerson(Person):
class Meta:
ordering = ["last_name"]
proxy = True
這裏,OrderedPerson並不是創建了一個表,而是代理排序方法。也就是說,使用Person的檢索方法並不會按last_name排序,而使用OrderedPerson檢索出來的結果是按last_name排序的。OrderedPerson使用與Person類一樣的檢索方法。
OrderPerson返回的queryset自然是Person的,這是當然的。我們不能要求django返回OrderedPerson類的queryset,因爲OrderedPerson只是代理而已,又不是真實的數據庫表類。
注意的是,proxy model不能繼承於抽象類,這是因爲代理model是操作連接數據庫的,也不能多重繼承~因爲你多重繼承了,代理model就不知道去哪個父類找屬性了
如果不指定代理model的manage,則代理model會自動繼承父類的manage。我們也可以手動設置代理model的manage,這樣,代理模型和父類模型的manage就分開了
3、proxy model(代理model)
爲代理模型添加manage有兩種方法:
一是直接在代理模型中直接指定manage
class NewManager(models.Manager):
...
class MyPerson(Person):
objects = NewManager()
class Meta:
proxy = True
另外一種是當你不想覆蓋父類模型中的manage但又想添加額外的manage,我們可以新建一個抽象模型,然後定義其manage,之後繼承該抽象模型,如:
# Create an abstract class for the new manager.
class ExtraManagers(models.Model):
secondary = NewManager()
class Meta:
abstract = True
class MyPerson(Person, ExtraManagers):
class Meta:
proxy = True