Tutorial

The main feature of pyrocumulus is automatic create restful APIs for mongodb documents. Let’t try it!

Creating a new project

First, create a new project using the pyrocumulus command in your command line:

$ pyrocumulus createproject ~/pyrotut
$ cd ~/pyrotut

Writing your models with mongoengine

In this tutorial, we’ll use the same models used on mongoengine tutorial. So, in the file pyrotut/models.py, write these models:

from mongoengine import Document, EmbeddedDocument
from mongoengine.fields import (StringField, ReferenceField, IntField,
                                EmbeddedDocumentField, ListField)


class User(Document):
    email = StringField(required=True)
    first_name = StringField(max_length=50)
    last_name = StringField(max_length=50)


class Comment(EmbeddedDocument):
    content = StringField()
    name = StringField(max_length=120)


class Post(Document):
    title = StringField(max_length=120, required=True)
    # reverse_delete_rule=CASCADE
    authors = ListField(ReferenceField(User, reverse_delete_rule=2))
    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()

Configuring the restful api

Using the models we created earlier, lets create a pyrocumulus.web.applications.RestApplication instance.

In the file pyrotut/web.py, write the following code:

from pyrocumulus.web.applications import RestApplication
from pyrotut.models import User, TextPost, LinkPost, ImagePost

simple_blog_api = RestApplication(User, TextPost, LinkPost, ImagePost)

And that’s it. You have a rest API for your documents.

Setting up config

Before we run our application, we need to set up some config variables. So, in the file settings.py, change your database settings and the APPLICATIONS variable

PROJECT_NAME = 'pyrotut'
TORNADO_PORT = 8888

DATABASE = {'default': {'HOST': 'localhost',
                        'PORT': 27017,
                        'NAME': 'pyrotut'}}

# list of applications to be served by tornado
APPLICATIONS = ['pyrotut.web.simple_blog_api',]

And that’s it. We have a new project created. Now, let’s try out something.

Testing the API

For testing, we’ll use the package requests, so, install it.

$ pip install requests

Now, is time to test our api, but first, lets see which url were mapped by our RestApplication.

>>> from pyrotut.web import application
>>> application.urls
[('/api/user/(.*)', ...),
 ('/api/textpost/comments/(.*)', ...),
 ('/api/textpost/(.*)', ...),
 ('/api/linkpost/comments/(.*)', ...),
 ('/api/linkpost/(.*)', ...),
 ('/api/imagepost/comments/(.*)', ...),
 ('/api/imagepost/(.*)', ...)]
>>>

As we can see, pyrocumulus.web.applications.RestApplication creates a url for each one of our Documents, and URLs for its EmbeddedDocuments too. Then, we can send HTTP requests to it and use our automatic api.

So, first, lets run a instance of the tornado web server and then open a Python shell and test our application.

$ python pyromanager.py runtorando --daemonize
$ python

Now, inside the python shell, we can start sending requests to our application

>>> import requests
>>> # base url for api
>>> base_url = 'http://localhost:8888/api/'
>>> user_url = base_url + 'user/'
>>> post_url = base_url + 'textpost/'
>>> comments_url = post_url + 'comments/'

First, create a user to be the posts’ author

>>> user_email = 'user@email.com'
>>> first_name = 'user'
>>> last_name = 'niceGuy'
>>> params = {'email': user_email,
...           'first_name': first_name,
...           'last_name': last_name}
...
>>> response = requests.put(user_url, params)
>>> response.connection.close()
>>> user_id = response.json()['id']
>>> user_id
'52ba237a7c1c8452919d03f8'

Now, create a post using the user created earlier

>>> post_title = 'My First Post'
>>> post_content = """Mussum ipsum cacilds, vidis litro abertis. """
>>> params = {'title': post_title,
...           'content': post_content,
...           'tags': ['pyrotut', 'pyrocumulus', 'mussum'],
...           'authors': [user_id]}
...
>>> response = requests.put(post_url, params)
>>> response.connection.close()
>>> post_id = response.json()['id']
>>> post_id
'52ba23be7c1c8452919d03f9'

And then, make a comment!

>>> comment_name = 'john doe'
>>> comment_content = 'bla bla bla...'
>>> params = {'name': comment_name,
...           'content': comment_content,
...           'parent_id': post_id}
...
>>> response = requests.put(comments_url, params)
>>> response.connection.close()
>>> response = requests.get(post_url, params={'id': post_id})
>>> response.connection.close()
post_content = response.json()['content']
>>> print(post_content)
Mussum ipsum cacilds, vidis litro abertis.
>>> post_comments = response.json()['comments']
>>> post_comments
[{'name': 'john doe', 'content': 'bla bla bla...'}]

That’s it. We created a user, a post and then sent a comment to that post. When retrieving the post, we get the comments list together, because our handler has as default depth the value 1. If you want only the comments list, to paginate them, you can use:

>>> requests.get(comments_url + 'list', params={'parent_id': post_id,
...                                             'page': 1, 'max': 10})