在 Django 中使用 MongoDB

每個Django工程師在接觸NOSQL數據庫的時候,確定都會思考一個問題:在Django中不能像操做普通的關係型數據庫(如下簡稱RDB)同樣,操做NOSQL數據庫嗎?固然能夠,Django工程師幾乎不須要什麼學習成本,就能使用NOSQL數據庫——由於有mongoengine這個模塊。web

MongoEngine由Python語言寫成,提供一個很相似Django ORM的API,本文介紹mongoengine的基本使用,主要是數據結構的定義和內聯表單的使用。數據庫

Install & Begin

須要安裝兩個模塊,pymongo和mongoenginedjango

pip install -U mongoengine
pip install pymongojson

如今咱們以最快的方式利用Django對MongoDB進行操做,請在電腦旁放置一個秒錶,理論上完成這些操做的時間不會超過3分鐘:數組

新建一個應用,其中新建一個docs.py文件,代碼以下:數據結構

from mongoengine import *
connect('test')

class User(Document):
    username = StringField(required=True)
    website = URLField()
    tags = ListField(StringField(max_length=16))學習

而後編輯views.py文件:ui

from django.http import HttpResponse
from . import docs

def index(request):
    user1 = docs.User(
        username='Perchouli',
        website='http://dmyz.org',
        tags = ['Web','Django','JS']
    )
    user1.save()
    Oid = user1.id
    return HttpResponse(Oid)設計

最後,把視圖加到URL中,訪問這個視圖能夠看到返回的ObjectID,咱們已經實現了對NOSQL數據庫的寫入和查找了。是否是和Django ORM幾乎同樣呢?orm

Philosophy

回頭說說代碼。docs.py中的語法很相似models.py,但二者的用途徹底不一樣。mongoengine是定義一個scheme,這些定義不會寫入到數據庫中。

在User中使用了三種Field,MongoDB是使用JSON格式存儲數據,因此寫入的值也能夠是對象/數組/字典,mongoengine會自動將Python數據格式轉換成JS數據格式,但必須按照以前的定義的Field類型來傳值。好比上例中的tags被定義爲數組(ListField),數組中的每一個元素是字符(StringField),mongoengine只接受一樣類型的數據格式。

EmbeddedField

RDB對數據的組織是創建在「關係」之上的,好比咱們要存儲某個用戶的Profile,它與用戶ID是多對一的關係,在RDB中,一般要新建一張名爲Profile的表,其中包含UserID和Profile,每一條數據對應一個Profile的記錄,這種方式多少顯得有些笨拙。NOSQL的出現解決了這類問題,在NOSQL數據庫中使用內聯的方式,直接把Profile存在User下,調用User時就能夠得到Profile的數據了。

修改上例中的docs.py,增長Profile:

from mongoengine import *
connect('test')
#先定義名爲Profile的EmbeddedDocument
class Profile(EmbeddedDocument):
    gender = StringField()
    location = StringField()

class User(Document):
    username = StringField(required=True)
    website = URLField()
    tags = ListField(StringField(max_length=16))
    #添加到User
    profile = EmbeddedDocumentField(Profile)

再修改views.py,爲了顯示區別這裏輸出一個JSON格式的字符串:

from django.http import HttpResponse
from . import docs

def index(request):
    profile1 = docs.Profile(gender='male', location='Beijing')
    user1 = docs.User(
        username='Perchouli',
        website='http://dmyz.org',
        tags = ['Web','Django','JS'],
        profile = profile1
    )
    user1.save()
    user1_json = str(user1.to_mongo())
    return HttpResponse(user1_json)

怎麼讀取profile中的gender和location?我不說你可能也想到了: user1.profile.gender。其餘的操做也同樣,都是用for來遍歷數據,查找、刪除也是相似的語法。

Afterword

mongoengine這種相似ORM的寫法提供了一個很好的過渡方式,但NOSQL數據庫畢竟不是構建於」關係」之上的,不少ORM的經驗並不適用。其實操做NOSQL數據庫,對它進行增刪改查並不複雜,真正頭疼的是數據的建模,具體的業務邏輯,怎樣設計才能最大限度的發揮NOSQL數據庫的用途等等一些列問題。mongoengine下降了Django工程師使用NOSQL數據庫的門檻,相信只要有更多的人蔘與其中,這類經驗會逐步豐富和完善的。

相關文章
相關標籤/搜索