mongodb-api-framework

Python toolset for rapid API development for MongoDb, built top on aiohttp and motor.


Keywords
mongodb, motor, rest, view, api, aiohttp, async, async/await
License
Other
Install
pip install mongodb-api-framework==0.0.23

Documentation

MongoDB API framework

Build Status Coverage Status

About

MongoDB API framework is a toolset for rapid API development.

Server-side example:

from typing import Dict
from datetime import datetime
from bson import ObjectId
from motor.motor_asyncio import AsyncIOMotorClient

from validate_it import Schema, StrField, ObjectIdField, DictField
from mongodb_api_framework.api import DocumentHook, RequestHook, HttpResource
from mongodb_api_framework.api.config import Get, Post, Put


class ArticleSchema(Schema):
    _id = ObjectIdField()
    
    title = StrField(required=True, min_length=4, max_length=160)
    text = StrField(required=True, min_length=100, max_length=4000)
    
    author = StrField(required=True)
    
    is_published = BoolField(required=True)
    created_at = DatetimeField(required=True)


# remove fields which user can't edit
UserArticleSchema = ArticleSchema().exclude('_id', 'author', 'is_published', 'created_at')


# allow filter only by title and text
class GetFilterSchema(Schema):
     title = DictField()
     text = DictField()


# allow filter by _id
class PutFilterSchema(Schema):
    _id = ObjectIdField()
    
    
class AddAuthor(DocumentHook):
    async def before_db_query(self, sandbox: Dict, document: Dict) -> Dict:
        document['author'] = sandbox['session']['user']['email']
        return document
        
        
class AddCreatedAt(DocumentHook):
    async def before_db_query(self, sandbox: Dict, document: Dict) -> Dict:
        document['created_at'] = datetime.now()
        return document


class SessionFromCookies(RequestHook):
    async def before_db_query(self, sandbox: Dict):
        _id = sandbox['request'].cookies.get('session_id')

        if _id:
            _session = await sandbox['resource'].db.session.find_one(
                {'_id': ObjectId(_id), 'is_archived': False}
            )
            if _session:
                sandbox['session'] = _session


class ArticleResource(HttpResource):
    collection_name = 'user_article'

    get = Get(
        output=ArticleSchema()
        """ validate document prepared for user """

        filter=GetFilterSchema()
        """ restrict mongodb filter """

        hooks=[
            SessionFromCookies()
        ]
        """ do something with request or document """
    )

    post = Post(
        input=UserArticleSchema(),
        """ validate user document """

        db=ArticleSchema()
        """ validate document before insert into collection """

        hooks=[
            SessionFromCookies(),
            AddAuthor(),
            AddCreatedAt()
        ]
        """ do something with request or document """
    )

    put = Put(
        input=UserArticleSchema(),
        """ validate user document """

        db=ArticleSchema()
        """ validate document before update in db """

        hooks=[
            SessionFromCookies()
        ]
        """ do something with request or document """
    )

# init `motor`
client = AsyncIOMotorClient()
db = client.test_database

# create `aiohttp` app
app = Application()

# register resource
app.add_rest_route('/rest/v1/article', ArticleResource(db=db))

Python client-side example:

import requests

article = {
    'title': 'Article example title',
    'text': 'Article example text'
}

requests.post('/rest/v1/article', json=article)

Installation

With pip:

pip install mongodb-api-framework

Requirements

Tested with python3.6, motor==1.2.1 and mongodb 3.4, aiohttp==3.0.7

Contribution how-to

Run tests:
  • clone repo: git clone <your-fork>
  • create and activate your virtualenv
  • pip install -r requirements.txt && pip install -r dev-requirements
  • ./run_tests.sh