在 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数据库的门槛,相信只要有更多的人参与其中,这类经验会逐步丰富和完善的。

相关文章
相关标签/搜索