(動態模型類,我的獨創)Django的原生ORM框架如何支持MongoDB,同時應對客戶使用時隨時變動字段


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類。當執行上述動態類定義過程時,就會觸發解析。

   通過上述處理,我們就能實現對數據庫插入作者字段了。數據庫中內容如下:

 

 

 

 

 

   


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM