MongoEngine中文入门教程(Python)

MongoEngine中文入门教程

翻译整理自官方文档 http://docs.mongoengine.org/tutorial.html


本教程通过创建一个简单的微博客(tumblelog)来学习MongoEngine。

1 安装MongoEngine

只需要使用pip安装即可,命令:

$ python -m pip install mongoengine

使用connect功能函数。第一个参数是要连接的数据库的名称:

from mongoengine import *
​
connect('tumblelog')

默认情况下,MongoEngine假定实例在端口27017的localhost端口运行。如果MongoDB在其他地方运行,则应提供hostport参数 connect()

connect('project', host='192.168.1.35', port=12345)

如果数据库需要身份验证,应提供usernamepasswordauthentication_source参数:

connect('project', username='webapp', password='pwd123', authentication_source='admin')

URI风格的连接,也支持-只需提供该URI作为hostconnect()

connect('project1', host='mongodb://localhost/database_name')

2 定义文件

MongoDB是无模式的,但是为文档定义模式可以帮助消除涉及错误类型或缺少字段的错误,还可以像传统ORM一样,在我们的文档上定义实用程序方法 。

本例中需要的信息类型有:

  • 用户

  • 帖子

  • 标签

  • 评论

用户User:定义User可能具有的字段以及它们可能存储的数据类型:

class User(Document):
    email = StringField(required=True)
    first_name = StringField(max_length=50)
    last_name = StringField(max_length=50)

看起来类似于在常规ORM中如何定义表的结构。关键区别在于,该架构永远不会传递给MongoDB,只会在应用程序级别强制实施,从而使将来的更改易于管理。同样,用户文档将存储在MongoDB集合中,而不是表中。

帖子Post: 区别于关系型数据库,们会将所有帖子存储在一个集合中,每种帖子类型只会存储所需的字段。例如如果以后要添加视频帖子,只需开始使用支持视频帖子所需的新字段即可。这很好地符合了面向对象的继承原则。我们可以认为 Post作为基类,并且TextPostImagePostLinkPost作为子类Post。实际上,MongoEngine开箱即用地支持这种建模-需要做的就是通过allow_inheritance在中将True设置为True来打开继承meta

class Post(Document):
    title = StringField(max_length=120, required=True)
    author = ReferenceField(User)
​
    meta = {'allow_inheritance': True}
​
class TextPost(Post): # 文本
    content = StringField()
​
class ImagePost(Post): # 图像
    image_path = StringField()
​
class LinkPost(Post):  # 链接
    link_url = StringField()

使用ReferenceField对象存储对帖子作者的引用 。这些与传统ORM中的外键字段相似,并且在保存时会自动转换为引用,在加载时会取消引用。

将标签直接作为字符串存储在帖子中。

class Post(Document):
    title = StringField(max_length=120, required=True)
    author = ReferenceField(User)
    tags = ListField(StringField(max_length=30))

评论Comment:作为嵌入式文档列表 直接存储在发布文档上。

class Comment(EmbeddedDocument):
    content = StringField()
    name = StringField(max_length=120)

相应地:

class Post(Document):
    title = StringField(max_length=120, required=True)
    author = ReferenceField(User)
    tags = ListField(StringField(max_length=30))
    comments = ListField(EmbeddedDocumentField(Comment))

处理删除:该ReferenceField对象使用关键字 reverse_delete_rule来处理删除规则。

class Post(Document):
    title = StringField(max_length=120, required=True)
    author = ReferenceField(User, reverse_delete_rule=CASCADE)
    tags = ListField(StringField(max_length=30))
    comments = ListField(EmbeddedDocumentField(Comment))

3 向Tumblelog中添加数据

创建User对象;

ross = User(email='ross@example.com', first_name='Ross', last_name='Lawley').save()

或使用属性语法定义:

ross = User(email='ross@example.com')
ross.first_name = 'Ross'
ross.last_name = 'Lawley'
ross.save()

同样的添加新用户john。

之后添加几篇帖子:

post1 = TextPost(title='Fun with MongoEngine', author=john)
post1.content = 'Took a look at MongoEngine today, looks pretty cool.'
post1.tags = ['mongodb', 'mongoengine']
post1.save()
​
post2 = LinkPost(title='MongoEngine Documentation', author=ross)
post2.link_url = 'http://docs.mongoengine.com/'
post2.tags = ['mongoengine']
post2.save()

4 数据访问

每个文档类(即直接或间接继承的任何类Document)都有一个objects属性,该属性用于访问与该类关联的数据库集合中的文档。如获取帖子标题:

for post in Post.objects:
    print(post.title)

访问特定类型:

for post in TextPost.objects:
    print(post.content)

使用TextPost的objects属性仅返回使用创建的文档TextPost。实际上,这里有一个更通用的规则:objects任何子类的属性Document 仅查找使用该子类或其子类之一创建的文档。

显示所有帖子,仅显示与每个帖子的特定类型相对应的信息:

for post in Post.objects:
    print(post.title)
    print('=' * len(post.title))
​
    if isinstance(post, TextPost):
        print(post.content)
​
    if isinstance(post, LinkPost):
        print('Link: {}'.format(post.link_url))

打印每个帖子的标题,如果是文本帖子,则显示内容,如果是链接帖子,则显示“链接“。

通过标签搜索帖子:

返回带有标签“ mongodb”的帖子:

for post in Post.objects(tags='mongodb'):
    print(post.title)

也有可用方法QuerySet 的对象,允许不同的结果被返回,例如,要求 first()objects属性将返回一个单一的文件,通过所提供的查询第一个匹配。聚合函数也可以用于QuerySet对象:

num_posts = Post.objects(tags='mongodb').count()
print('Found {} posts with tag "mongodb"'.format(num_posts))

 

入门教程结束,若需要更深入的了解推荐参阅官方完整用户指南

 


附录1:

上例代码:

from mongoengine import *

class User(Document):
    email = StringField(required=True)
    first_name = StringField(max_length=50)
    last_name = StringField(max_length=50)

class Comment(EmbeddedDocument):
    content = StringField()
    name = StringField(max_length=120)

class Post(Document):
    title = StringField(max_length=120, required=True)
    author = ReferenceField(User, reverse_delete_rule=CASCADE)
    tags = ListField(StringField(max_length=30))
    comments = ListField(EmbeddedDocumentField(Comment))
    meta = {'allow_inheritance': True}

class TextPost(Post):
    content = StringField()

class ImagePost(Post):
    image_path = StringField()

class LinkPost(Post):
    link_url = StringField()

def createDBs():

    ross = User(email='ross@example.com', first_name='Ross', last_name='Lawley').save()
    john = User(email='john@example.com', first_name='John', last_name='O.o').save()

    post1 = TextPost(title='Fun with MongoEngine', author=john)
    post1.content = 'Took a look at MongoEngine today, looks pretty cool.'
    post1.tags = ['mongodb', 'mongoengine']
    post1.save()

    post2 = LinkPost(title='MongoEngine Documentation', author=ross)
    post2.link_url = 'http://docs.mongoengine.com/'
    post2.tags = ['mongoengine']
    post2.save()

#createDBs()  第一次运行先创建

connect('tumblelog')

for post in Post.objects:
    print(post.title)
    print('=' * len(post.title))

    if isinstance(post, TextPost):
        print(post.content)

    if isinstance(post, LinkPost):
        print('Link: {}'.format(post.link_url))

num_posts = Post.objects(tags='mongoengine').count()
print('Found {} posts with tag "mongodb"'.format(num_posts))

附录2 常用MongoDB命令:

docker exec -it mongo mongo  docker进入MongoDB
show dbs   显示所有数据库
use  XXX   进入某数据库
show tables  显示所有表格
db.YYY.find().pretty() 显示某表的内容
db.dropDatabase()  删除数据库
  • 1
    点赞
  • 7
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值