django模型的繼承

很多時候,我們都不是從‘一窮二白’開始編寫模型的,有時候可以從第三方庫中繼承,有時候可以從以前的代碼中繼承,甚至現寫一個模型用于被其它模型繼承。這樣做的好處,我就不贅述了,每個學習Django的人都非常清楚。

類同于Python的類繼承,Django也有完善的繼承機制。

Django中所有的模型都必須繼承django.db.models.Model模型,不管是直接繼承也好,還是間接繼承也罷。

你唯一需要決定的是,父模型是否是一個獨立自主的,同樣在數據庫中創建數據表的模型,還是一個只用來保存子模型共有內容,并不實際創建數據表的抽象模型。

Django有三種繼承的方式:

  • 抽象基類:被用來繼承的模型被稱為Abstract base classes,將子類共同的數據抽離出來,供子類繼承重用,它不會創建實際的數據表;
  • 多表繼承:Multi-table inheritance,每一個模型都有自己的數據庫表;
  • 代理模型:如果你只想修改模型的Python層面的行為,并不想改動模型的字段,可以使用代理模型。

注意!同Python的繼承一樣,Django也是可以同時繼承兩個以上父類的!

一、 抽象基類:

只需要在模型的Meta類里添加abstract=True元數據項,就可以將一個模型轉換為抽象基類。Django不會為這種類創建實際的數據庫表,它們也沒有管理器,不能被實例化也無法直接保存,它們就是用來被繼承的。抽象基類完全就是用來保存子模型們共有的內容部分,達到重用的目的。當它們被繼承時,它們的字段會全部復制到子模型中。看下面的例子:

from django.db import modelsclass 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) 

Student模型將擁有name,age,home_group三個字段,并且CommonInfo模型不能當做一個正常的模型使用。

抽象基類的Meta數據:

如果子類沒有聲明自己的Meta類,那么它將繼承抽象基類的Meta類。下面的例子則擴展了基類的Meta:

from django.db import modelsclass CommonInfo(models.Model): # ... class Meta: abstract = True ordering = ['name'] class Student(CommonInfo): # ... class Meta(CommonInfo.Meta): db_table = 'student_info' 

這里有幾點要特別說明:

  • 抽象基類中有的元數據,子模型沒有的話,直接繼承;
  • 抽象基類中有的元數據,子模型也有的話,直接覆蓋;
  • 子模型可以額外添加元數據;
  • 抽象基類中的abstract=True這個元數據不會被繼承。也就是說如果想讓一個抽象基類的子模型,同樣成為一個抽象基類,那你必須顯式的在該子模型的Meta中同樣聲明一個abstract = True
  • 有一些元數據對抽象基類無效,比如db_table,首先是抽象基類本身不會創建數據表,其次它的所有子類也不會按照這個元數據來設置表名。

如果在你的抽象基類中存在ForeignKey或者ManyToManyField字段,并且使用了related_name或者related_query_name參數,那么一定要小心了。因為按照默認規則,每一個子類都將擁有同樣的字段,這顯然會導致錯誤。為了解決這個問題,當你在抽象基類中使用related_name或者related_query_name參數時,它們兩者的值中應該包含%(app_label)s%(class)s部分:

  • %(class)s用字段所屬子類的小寫名替換
  • %(app_label)s用子類所屬app的小寫名替換

例如,對于common/models.py模塊:

from django.db import modelsclass Base(models.Model): m2m = models.ManyToManyField( OtherModel, related_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 

對于另外一個應用中的rare/models.py:

from common.models import Baseclass ChildB(Base): pass 

對于上面的繼承關系:

  • common.ChildA.m2m字段的reverse name(反向關系名)應該是common_childa_relatedreverse query name(反向查詢名)應該是common_childas
  • common.ChildB.m2m字段的反向關系名應該是common_childb_related;反向查詢名應該是common_childbs
  • rare.ChildB.m2m字段的反向關系名應該是rare_childb_related;反向查詢名應該是rare_childbs

當然,如果你不設置related_name或者related_query_name參數,這些問題就不存在了。


二、 多表繼承

這種繼承方式下,父類和子類都是獨立自主、功能完整、可正常使用的模型,都有自己的數據庫表,內部隱含了一個一對一的關系。例如:

from django.db import modelsclass 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將包含Place的所有字段,并且各有各的數據庫表和字段,比如:

>>> Place.objects.filter(name="Bob's Cafe")
>>> Restaurant.objects.filter(name="Bob's Cafe")

如果一個Place對象同時也是一個Restaurant對象,你可以使用小寫的子類名,在父類中訪問它,例如:

>>> p = Place.objects.get(id=12)
# 如果p也是一個Restaurant對象,那么下面的調用可以獲得該Restaurant對象。
>>> p.restaurant
<Restaurant: ...>

但是,如果這個Place是個純粹的Place對象,并不是一個Restaurant對象,那么上面的調用方式會彈出Restaurant.DoesNotExist異常。

讓我們看一組更具體的展示,注意里面的注釋內容。

>>> from app1.models import Place, Restaurant # 導入兩個模型到shell里 >>> p1 = Place.objects.create(name='coff',address='address1') >>> p1 # p1是個純Place對象 <Place: Place object> >>> p1.restaurant # p1沒有餐館屬性 Traceback (most recent call last): File "<console>", line 1, in <module> File "C:\Python36\lib\site-packages\django\db\models\fields\related_descriptors.py", line 407, in __get__ self.related.get_accessor_name() django.db.models.fields.related_descriptors.RelatedObjectDoesNotExist: Place has no restaurant. >>> r1 = Restaurant.objects.create(serves_hot_dogs=True,serves_pizza=False) >>> r1 # r1在創建的時候,只賦予了2個字段的值 <Restaurant: Restaurant object> >>> r1.place # 不能這么調用 Traceback (most recent call last): File "<console>", line 1, in <module> AttributeError: 'Restaurant' object has no attribute 'place' >>> r2 = Restaurant.objects.create(serves_hot_dogs=True,serves_pizza=False, name='pizza', address='address2') >>> r2 # r2在創建時,提供了包括Place的字段在內的4個字段 <Restaurant: Restaurant object> >>> r2.place # 可以看出這么調用都是非法的,異想天開的 Traceback (most recent call last): File "<console>", line 1, in <module> AttributeError: 'Restaurant' object has no attribute 'place' >>> p2 = Place.objects.get(name='pizza') # 通過name,我們獲取到了一個Place對象 >>> p2.restaurant # 這個P2其實就是前面的r2 <Restaurant: Restaurant object> >>> p2.restaurant.address 'address2' >>> 

轉載于:https://www.cnblogs.com/navysummer/p/10200167.html

本文來自互聯網用戶投稿,該文觀點僅代表作者本人,不代表本站立場。本站僅提供信息存儲空間服務,不擁有所有權,不承擔相關法律責任。
如若轉載,請注明出處:http://www.pswp.cn/news/387664.shtml
繁體地址,請注明出處:http://hk.pswp.cn/news/387664.shtml
英文地址,請注明出處:http://en.pswp.cn/news/387664.shtml

如若內容造成侵權/違法違規/事實不符,請聯系多彩編程網進行投訴反饋email:809451989@qq.com,一經查實,立即刪除!

相關文章

SpringBoot部署項目到Docker倉庫

SpringBoot部署項目到Docker倉庫1.開啟遠程控制端口Centos7開啟方式&#xff1a; vim /lib/systemd/system/docker.service找到ExecStart行 ExecStart/usr/bin/dockerd -H tcp://0.0.0.0:2375 -H unix:///var/run/docker.sock 重啟docker 啟動 systemctl start docker守護進程…

人臉識別經典方法

這篇文章是擼主要介紹人臉識別經典方法的第一篇&#xff0c;后續會有其他方法更新。特征臉方法基本是將人臉識別推向真正可用的第一種方法&#xff0c;了解一下還是很有必要的。特征臉用到的理論基礎PCA在另一篇博客里&#xff1a;特征臉(Eigenface)理論基礎-PCA(主成分分析法)…

Jquery常用正則驗證

常用校驗的正則表達式var rulesConfig { /** * str.replace(/^\s|\s$/g, ) 解析&#xff1a; str&#xff1a;要替換的字符串 \s : 表示 space &#xff0c;空格 &#xff1a; 一個或多個 ^&#xff1a; 開始&#xff0c;^\s&#xff0c;以空格開始 $&#xff1a; 結束&#x…

svm參數說明

svm參數說明---------------------- 如果你要輸出類的概率&#xff0c;一定要有-b參數 svm-train training_set_file model_file svm-predict test_file model_fileoutput_file 自動腳本&#xff1a;Python easy.py train_data test_data 自動選擇最優參數&#xff0c;自動進行…

poj-3667(線段樹區間合并)

題目鏈接&#xff1a;傳送門 參考文章&#xff1a;傳送門 思路&#xff1a;線段樹區間合并問題&#xff0c;每次查詢到滿足線段樹的區間最左值&#xff0c;然后更新線段樹。 #include<iostream> #include<cstdio> #include<cstring> using namespace std; co…

面試題編程題11-python 生成隨機數

隨機整數&#xff1a; random.randint(a,b), [a,b] random.randrange(a,b,step) [a,b) 隨機實數 random.random()返回0 到1 之間的浮點數轉載于:https://www.cnblogs.com/feihujiushiwo/p/10922454.html

車牌識別之顏色選取

車牌定位是車牌識別中第一步&#xff0c;也是最重要的一步。 由于中國車牌種類多樣&#xff0c;顏色不一&#xff0c; 再加上車牌經常有污損&#xff0c;以及車牌周圍干擾因素太多&#xff0c;都成為了車牌定位的難點。 這里首先使用最簡單算法來描述車牌定位&#xff0c;以及他…

Python - 排序( 插入, 冒泡, 快速, 二分 )

插入排序 算法分析 兩次循環, 大循環對隊列中的每一個元素拿出來作為小循環的裁定對象 小循環對堆當前循環對象在有序隊列中尋找插入的位置 性能參數 空間復雜度  O(1) 時間復雜度  O(n^2) 詳細代碼解讀 import randomdef func(l):# 外層循環: 對應遍歷所有的無序數據for i…

[EmguCV|C#]使用CvInvoke自己繪製色彩直方圖-直方圖(Hitsogram)系列(4)

2014-02-0610325 0C# 檢舉文章 過年結束了&#xff0c;雖然還是學生所以其實還有兩個禮拜的假期&#xff0c;不過為了不讓自己發慌&#xff0c;趁著假期多利用充實自己&#xff0c;所以提早回到開工狀態&#xff0c;而這次總算要把一直說的自己動手繪製猜色直方圖文章寫出。 …

G.點我

鏈接&#xff1a;https://ac.nowcoder.com/acm/contest/903/G 題意&#xff1a; X腿與隊友到河北省來參加2019河北省大學生程序設計競賽&#xff0c;然而這場比賽的題目難度實在是太高了。比賽開始一個小時后&#xff0c;X腿仍然沒有做出一個題。這時候&#xff0c;X腿驚訝的發…

輪廓的查找、表達、繪制、特性及匹配(How to Use Contour? Find, Component, Construct, Features Match)

前言 輪廓是構成任何一個形狀的邊界或外形線。前面講了如何根據色彩及色彩的分布&#xff08;直方圖對比和模板匹配&#xff09;來進行匹配&#xff0c;現在我們來看看如何利用物體的輪廓。包括以下內容&#xff1a;輪廓的查找、表達方式、組織方式、繪制、特性、匹配。 查…

Android:IntentService的學習

在Android的四大組件中&#xff0c;Service排行老二&#xff0c;在Android中的主要作用是后臺服務&#xff0c;進行與界面無關的操作。由于Service運行在主線程&#xff0c;所以進行異步操作需要在子線進行。為此Android為我們提供了IntentService。 IntentService是一個抽象類…

智能商業大會構造信息化交流平臺

在快速發展的當今社會&#xff0c;所有事物都在日新月異地變化著&#xff0c;相較于過去的傳統商業的變化速度&#xff0c;現今基于數據的互聯網商業變化速度高出了一個量級&#xff0c;同時市場對于企業的應對速度也有了更高的要求&#xff0c;然而面對大體量的數據&#xff0…

itcast-ssh-crm實踐

分析 BaseDao 文件上傳 轉載于:https://www.cnblogs.com/hellowq/p/10209761.html

分類器大牛們

David Lowe&#xff1a;Sift算法的發明者&#xff0c;天才。 Rob Hess&#xff1a;sift的源碼OpenSift的作者&#xff0c;個人主頁上有openSift的下載鏈接&#xff0c;Opencv中sift的實現&#xff0c;也是參考這個。 Koen van de Sande&#xff1a;作者給出了sift,densesift,co…

go 成長路上的坑(1)

一、先來看一段代碼 package mainimport "fmt"type X struct{}func (x *X) test(){println("h1",x) } func main(){a : X{} a.test()(&X{}).test()(X{}).test() } 猜猜他的結果 二、揭曉答案 package mainimport "fmt"type X struct{}func (…

利用python腳本程序監控文件被修改

需求&#xff1a;利用python編寫監控程序&#xff0c;監控一個文件目錄&#xff0c;當目錄下的文件發生改變時&#xff0c;實現有修改就發報警郵件 郵件使用QQ郵箱&#xff0c;需要開啟smtp&#xff0c;使用手機發生短信&#xff0c;騰訊會給你發郵箱密碼。如下所示&#xff1a…

Oracle RAC

環境如下&#xff1a; Linux操作系統&#xff1a;Centos 6.5 64bit &#xff08;這個版本的redhat 6內核等OS在安裝grid最后執行root.sh時會出現crs-4124&#xff0c;是oracle11.2.0.1的bug&#xff09; VMware version&#xff1a;Workstation 8.0.3 build-703057 Oracle…

好程序員web前端分享MVVM框架Vue實現原理

好程序員web前端分享MVVM框架Vue實現原理&#xff0c;Vue.js是當下很火的一個JavaScript MVVM庫&#xff0c;它是以數據驅動和組件化的思想構建的。相比于Angular.js和react.js更加簡潔、更易于理解的API&#xff0c;使得我們能夠快速地上手并使用Vue.js。?1.什么是MVVM呢&…

HDU - 3516 Tree Construction

HDU - 3516 思路&#xff1a; 平行四邊形不等式優化dp &#xff1a;&#xff09; 代碼&#xff1a; #pragma GCC optimize(2) #pragma GCC optimize(3) #pragma GCC optimize(4) #include<bits/stdc.h> using namespace std; #define y1 y11 #define fi first #define se…