web-dev-qa-db-ja.com

MongoKit対MongoEngine対Flask-MongoAlchemy Flask

Flask用のMongoKit、MongoEngine、またはFlask-MongoAlchemyの経験はありますか?

あなたはどちらを好みますか?肯定的または否定的な経験? Flask-Newbieのオプションが多すぎます。

71
r0sk

人気のあるPython MongoDBのORMを評価するのに多くの時間を費やしました。これは徹底的な演習でした。

私の結論は、ORMがMongoDBの楽しさを取り除くことです。当然のことではありません。最初にリレーショナルデータベースから遠ざかったのと同様の制限が課せられます。

繰り返しますが、私は本当にORMを使用したかったのですが、pymongoを直接使用することが道であると確信しています。今、MongoDB、pymongo、およびPythonを含むパターンに従います。

リソース指向アーキテクチャは、非常に自然な表現につながります。たとえば、次のユーザーリソースを使用します。

from werkzeug.wrappers import Response
from werkzeug.exceptions import NotFound

Users = pymongo.Connection("localhost", 27017)["mydb"]["users"]


class User(Resource):

    def GET(self, request, username):
        spec = {
            "_id": username,
            "_meta.active": True
        }
        # this is a simple call to pymongo - really, do
        # we need anything else?
        doc = Users.find_one(spec)
        if not doc:
            return NotFound(username)
        payload, mimetype = representation(doc, request.accept)
        return Response(payload, mimetype=mimetype, status=200)

    def PUT(self, request, username):
        spec = {
            "_id": username,
            "_meta.active": True
        }
        operation = {
            "$set": request.json,
        }
        # this call to pymongo will return the updated document (implies safe=True)
        doc = Users.update(spec, operation, new=True)
        if not doc:
            return NotFound(username)
        payload, mimetype = representation(doc, request.accept)
        return Response(payload, mimetype=mimetype, status=200)

Resource基本クラスは次のようになります

class Resource(object):

    def GET(self, request, **kwargs):
        return NotImplemented()

    def HEAD(self, request, **kwargs):
        return NotImplemented()

    def POST(self, request, **kwargs):
        return NotImplemented()

    def DELETE(self, request, **kwargs):
        return NotImplemented()

    def PUT(self, request, **kwargs):
        return NotImplemented()

    def __call__(self, request, **kwargs):
        handler = getattr(self, request.method)
        return handler(request, **kwargs)

WSGI仕様を直接使用し、可能な場合はWerkzeugを活用することに注意してください(ところで、FlaskWerkzeugに不要な複雑さを追加すると思います) 。

関数representationは、リクエストのAcceptヘッダーを受け取り、適切な表現を生成します(たとえば、application/json、またはtext/html)。実装するのは難しくありません。また、Last-Modifiedヘッダー。

もちろん、入力をサニタイズする必要があり、提示されたコードは機能しません(例としてそれを意味しますが、私のポイントを理解することは難しくありません)。

繰り返しになりますが、私はすべてを試しましたが、このアーキテクチャにより、コードは柔軟でシンプルで拡張可能になりました。

83
Escualo