Django中Model繼承的三種方式

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
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章