MongoKit против MongoEngine против Flask-MongoAlchemy for Flask

У кого-нибудь есть опыт работы с MongoKit, MongoEngine или Flask-MongoAlchemy for Flask?

Какой из них вы предпочитаете? Положительные или отрицательные переживания?. Слишком много вариантов для Flask-Newbie.

Ответ 1

Я потратил много времени на оценку популярных ORM Python для MongoDB. Это было исчерпывающее упражнение, поскольку я действительно хотел выбрать его.

Мой вывод состоит в том, что 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, где это возможно (кстати, я думаю, что Flask добавляет ненужное усложнение Werkzeug).

Функция representation принимает заголовки запроса Accept и создает подходящее представление (например, application/json или text/html). Это не сложно реализовать. Он также добавляет заголовок Last-Modified.

Конечно, ваш вклад нуждается в дезинфекции, и код, представленный, не будет работать (я имею в виду это как пример, но нетрудно понять мою точку зрения).

Опять же, я все испробовал, но эта архитектура сделала мой код гибким, простым и расширяемым.