pyramidでmongoengineを使ってみる
pythonのmongodb用ODM(ORM)であるmongoengineのお話です。
mongoengineでmongoのデータを更新するフォームの勉強をしたかったので、mongoengineを軽く触ってみました。
1. 環境構築
今回のテスト用にmyform環境を作成し「/form」をルーティングに追加します。
ちなみにSymfony2でtwigを使ってたのでテンプレートエンジンには書式が同じjinja2を設定してます。
// 必要モジュールのインストール $ pip install pyramid==1.3.4 $ pip install waitress $ pip install pyramid_jinja2 $ pip install mongoengine // プロジェクト作成 $ pcreate -s starter myform $ cd myform $ python setup.py develop // 「/form」をルーティングにしてテンプレートエンジンにjinja2を設定 $ vi myform/__init__.py from pyramid.config import Configurator from mongoengine import connect def main(global_config, **settings): """ This function returns a Pyramid WSGI application. """ config = Configurator(settings=settings) config.include('pyramid_jinja2') config.add_static_view('static', 'static', cache_max_age=3600) config.add_route('form_index', '/form') config.scan() connect('pyramid_form') return config.make_wsgi_app()
2. コレクション用のモデルを作成
「email」「first_name」「last_name」の文字列型のカラムを持った「user」コレクションのモデルを定義します。
$ mkdir myform/models $ touch myform/models/__init__.py $ vi myform/models/user.py from mongoengine import Document from mongoengine import StringField class User(Document): email = StringField(required=True) first_name = StringField(max_length=50) last_name = StringField(max_length=50)
3. データを挿入するviewを作成
Userモデルのインスタンスを生成して保存するビューとテンプレートを作成
// データを挿入するview $ vi myform/views.py from pyramid.view import view_config from models.user import User @view_config(route_name='form_index', renderer='templates/form/index.jinja2') def my_view(request): test = User(email='test1@example.com') test.first_name = 'test1_fname' test.last_name = 'test1_lname' test.save() return {'value':'test!'} // テンプレート作成 $ mkdir myform/templates/form/ $ vi myform/templates/form/index.jinja2 hello {{ value }}
4. サーバを起動して確認
サーバを起動後「/form」にアクセスすると「hello test!」と表示されます。
mongodbにデータが保存されている事が確認できます。
$ mongo MongoDB shell version: 2.4.5 connecting to: test > show dbs; local 0.078125GB pyramid_form 0.203125GB > show collections system.indexes user > var x = db.user.findOne(); > printjson(x) { "_id" : ObjectId("52345cfe2e5229637bcaa389"), "email" : "test1@example.com", "first_name" : "test1_fname", "last_name" : "test1_lname" }
5. EmbeddedDocumentの使用
mongodbの特性の1つにEmbeddedDocument機能があるので使ってみました。
「post」コレクションにCommentという埋め込みドキュメントを設定します。
$ vi myform/models/posts.py # --* encoding:utf-8 *-- from mongoengine import Document from mongoengine import EmbeddedDocument from mongoengine import StringField from mongoengine import ReferenceField from mongoengine import ListField from mongoengine import EmbeddedDocumentField from .user import User 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)) meta = {'allow_inheritance': True} class TextPost(Post): content = StringField() class ImagePost(Post): image_path = StringField() class LinkPost(Post): link_url = StringField() // TextPostとLinkPostの2つのインスタンスを作成して保存 $ vi myform/views.py from pyramid.view import view_config from models.user import User from models.posts import TextPost from models.posts import LinkPost from models.posts import Comment @view_config(route_name='form_index', renderer='templates/form/index.jinja2') def my_view(request): user = User(email='test2@example.com', first_name='test2_fname', last_name='test2_lname').save() comment = Comment(content='comment_content', name='comment_name') post1 = TextPost(title='Fun with MongoEngine', author=user) post1.content = 'Took a look at MongoEngine today, looks pretty cool.' post1.tags = ['mongodb', 'mongoengine'] post1.comments = [comment] post1.save() post2 = LinkPost(title='MongoEngine Documentation', author=user) post2.link_url = 'http://docs.mongoengine.com/' post2.tags = ['mongoengine'] post2.save() return {'value':'test!'}
6. EmbeddedDocumentの確認
mongoで確認するとauthorでUserとの関連が設定されて、commentsにコメントが埋め込まれている事が確認できます。
> db.post.find().forEach(printjson); { "_id" : ObjectId("52345fda2e52296395f90bdf"), "_cls" : "Post.TextPost", "title" : "Fun with MongoEngine", "author" : ObjectId("52345fda2e52296395f90bde"), "tags" : [ "mongodb", "mongoengine" ], "comments" : [ { "content" : "comment_content", "name" : "comment_name" } ], "content" : "Took a look at MongoEngine today, looks pretty cool." } { "_id" : ObjectId("52345fda2e52296395f90be0"), "_cls" : "Post.LinkPost", "title" : "MongoEngine Documentation", "author" : ObjectId("52345fda2e52296395f90bde"), "tags" : [ "mongoengine" ], "comments" : [ ], "link_url" : "http://docs.mongoengine.com/" }
さすがODMって感じです。
参考