From a4fd05eab62f1d79e677d60d1a6ba6b76e1b9ae5 Mon Sep 17 00:00:00 2001 From: Brett Langdon Date: Tue, 21 May 2013 20:56:22 -0400 Subject: [PATCH] initial commit --- .gitignore | 3 +++ README.md | 28 ++++++++++++++++++++ mongorest/__init__.py | 59 +++++++++++++++++++++++++++++++++++++++++++ setup.py | 12 +++++++++ 4 files changed, 102 insertions(+) create mode 100644 .gitignore create mode 100644 README.md create mode 100644 mongorest/__init__.py create mode 100644 setup.py diff --git a/.gitignore b/.gitignore new file mode 100644 index 0000000..39e6d08 --- /dev/null +++ b/.gitignore @@ -0,0 +1,3 @@ +*.egg-info +build +dist diff --git a/README.md b/README.md new file mode 100644 index 0000000..6736e4a --- /dev/null +++ b/README.md @@ -0,0 +1,28 @@ +mongorest +========= + +This is just a toy module for creating a REST interface to MongoDB which uses `jsonschema` +to validate data before trying to save into MongoDB collection. + +## Example + +This example creates a REST server with the following routes: +* `GET` `/users/` - return a single document from `users` as JSON or `204` +* `PUT` `/users/` - `PUT` a JSON document into `users` or `400` if data does not validate with the schema +* `GET` `/users` - get all documents from `users` as JSON + +```python +from mongorest import Server + +app = Server('test', host='my.db.server', port=27017) + +users_schema = {'type': 'object', + 'properties': { + 'name': {'type': 'string'}, + 'age': {'type': 'number', + 'minimum': 0}, + 'admin': {'type': 'boolean'}}, + 'required': ['name', 'age', 'admin']} +app.register_collection('users', users_schema) +app.run() +``` diff --git a/mongorest/__init__.py b/mongorest/__init__.py new file mode 100644 index 0000000..89211d4 --- /dev/null +++ b/mongorest/__init__.py @@ -0,0 +1,59 @@ +from bson.objectid import ObjectId +from flask import Flask, request +from flask.ext.restful import Resource, Api +from jsonschema import validate, ValidationError +from pymongo import MongoClient + + +def convert(docs): + for doc in docs: + doc['_id'] = str(doc['_id']) + yield doc + + +def generate_resource(collection, schema, db): + class CollectionResource(Resource): + def get(self, doc_id): + doc_id = ObjectId(doc_id) + doc = db[collection].find_one({'_id': doc_id}) + if doc is not None: + doc['_id'] = str(doc['_id']) + return doc, 200 + return '', 204 + + def put(self, doc_id): + try: + validate(request.json, schema) + doc = request.json + doc['_id'] = ObjectId(doc_id) + db[collection].save(doc) + except ValidationError, ve: + return str(ve), 400 + return '', 200 + + return CollectionResource + + +def generate_list(collection, db): + class CollectionList(Resource): + def get(self): + docs = db[collection].find() + return list(convert(docs)), 200 + return CollectionList + + +class Server(Api): + def __init__(self, database, host='127.0.0.1', port=27017): + self.app = Flask(__name__) + super(Server, self).__init__(self.app) + self.client = MongoClient(host, port) + self.db = self.client[database] + + def register_collection(self, collection, schema): + collection_resource = generate_resource(collection, schema, self.db) + collection_list = generate_list(collection, self.db) + self.add_resource(collection_resource, '/%s/' % collection) + self.add_resource(collection_list, '/%s' % collection) + + def run(self, *args, **kwargs): + self.app.run(*args, **kwargs) diff --git a/setup.py b/setup.py new file mode 100644 index 0000000..971eeb7 --- /dev/null +++ b/setup.py @@ -0,0 +1,12 @@ +#!/usr/bin/env python + +from setuptools import find_packages, setup + +setup(name='Mongo REST', + version='0.1.0', + description='MongoDB REST Server', + author='Brett Langdon', + author_email='brett@blangdon.com', + url='http://ww.github.com/brettlangdon/mongo-rest', + install_requires=['pymongo', 'flask', 'flask-restful', 'jsonschema'], + packages=find_packages())