1.背景知識
需要開發一個系統,處理大量EXCEL表格信息,各種類別。表格標題多變,因此使用不需要預先設計數據表結構的MongoDB,即NoSQL。一是字段不固定,二是同名字段可以存儲不同的字段類型。
同時,后端確定使用Django,原因是數據處理這一塊,python無敵於天下。
Django采用MVT模式開發。MODEL是最關鍵的部分。是ORM的核心。但是ORM主要用於關系型數據庫。那么如何解決?
2.大量調研的網上資料
(1)mongoengine
mongoengine(跟pymongodb類似,但是相比於后者,又能提供模型類的功能,封裝一些數據操作,不用單獨寫一堆crub)
缺點:經反復測試研究,不支持django的原生后台管理功能,因為無法將django的數據遷移到mongodb數據庫中因此無法使用原生的后台管理界面,需要定制。
(2)djongo(注意不是django。爹是django,媽是mongodb,交配出來的物種)
與Django支持的其它SQL數據庫類型,用於支持Nosql。
可以將django的數據遷移到mongodb數據庫中,也可以使用原生的后台管理界面
(3)Django-nonrel
django的分支,有時間可以研究一下。
3.目前的問題(用mongodb仿ORM,那么如何隨時變動字段?)
OVM模型的重點就是提前定義類的成員,同時遷移到數據表中,形成相應字段。
對於一個excel表,記錄圖書信息,比如,書名,出版日期。
我們只需要用下述方式定義一個類,
# 創建圖書類 class BookInfo(models.Model): """圖書模型類""" # 圖書名稱,CharField說明是該類屬性是一個字符串,max_length指定最大長度 book_title = models.CharField(max_length=20) # 出版日期,DateField說明該類屬性是一個日期 book_pub_date = models.DateField() def __str__(self): """覆蓋對BookInfo實例化對象使用str()的返回值""" return self.book_title # 返回書名
作為model放入django中。后面執行如下操作,數據庫就可以相應的自動變化了。
有djongo對django和mongodb支持,我們可以將mongodb“仿”為ORM模型,注意,是仿。
def get(request): # book=BookInfo() # book.book_title='水滸傳' # book.book_pub_date=date(1960,1,1) # book.save() # return HttpResponse('helloworld')
那么如何隨時變動字段呢?比如,哪天使用方的excel表格又變動了,增加了一列,比如作者。那么如何將作者這個字段加入呢?同時,不改變原始代碼?
4.解決方案(動態模型類)
(1)模型save的局限性
首先,python支持類成員隨時定義,我們直接在模型類對象中,添加一個成員。
# book.author = '羅貫中'
但是發現模型的save操作,對這個臨時增加的成員不處理,無法加入數據庫中。
save只處理在原始models.py文件中定義BookInfo的時候定義的固定類成員。
通過調試發現,Django在運行前需要首先對各個models.py進行解析。因此,后續在模型類實例化對象中臨時增加成員,是沒用的。
(2)我的方式:強制解析新的模型類,支持對字段進行變動,更好時候NoSQL
通過文件定義的類,具有一些特殊字段。__module__ __qualname和__doc__
由於Django只處理models.py文件中定義的模型類。所以,
在程序執行時,動態創建新的模型類,並且修改其成員屬性,把其仿真為文件中定義的模型類,然后再用django進行解析,使其能夠作為ORM的新model。
BookInfo = type('BookInfo', (models.Model,), {"__module__":"booktest.models",'__qualname__':'BookInfo',"__doc__":"注釋", "book_title": models.CharField(max_length=20),"book_pub_date" :models.DateField(),"author": models.CharField(max_length=20)})
book=BookInfo()
book.book_title='三國演義xxx'
book.book_pub_date=date(1960,1,1)
book.author='我是傑少啊'
book.save()
注意兩點:第一,由於內存中有原始模型類BookInfo,我們要對其完全覆蓋掉。
上面type為什么會觸發django重新解析模型類呢?
因為BookInfo繼承的model,核心是繼承Django的ModelBase類。當執行上述動態類定義過程時,就會觸發解析。
通過上述處理,我們就能實現對數據庫插入作者字段了。數據庫中內容如下: