django-ripozo tutorial

In this tutorial we will create a todo list application.

Setting up Django

Note This is not a tutorial for Django. If you need some more info on Django please visit: the django tutorial.

In this tutorial we will create a todo list application. First we need to install the necessary dependencies. It is recommended that you work within a virtualenv.

pip install django-ripozo

This should install an appropriate version of Django as well.

Now we need to create our project and app.

django-admin startproject todolist

You’ll need to sync your database.

python ./manage.py migrate

Now we need to create our todo app.

python ./manage.py startapp todoapp

Now in our todolist/settings.py we will want to add 'django_ripozo' and 'todoapp' to the INSTALLED_APPS tuple.

Alright, now we’re going to edit the todoapp/models.py file and add the following models.

class TaskBoard(models.Model):
    title = models.CharField(max_length=50)


class Task(models.Model):
    title = models.CharField(max_length=50)
    description = models.TextField()
    completed = models.BooleanField(default=False)
    task_board = models.ForeignKey('TaskBoard', related_name='task_set')

You’ll need to run makemigrations and migrate again.

You’re now all set up and ready to start building your api.

Creating your managers

Managers are responsible for handling access to the django models that you just created. To start we are going to create a new file in the todoapp called managers.py. After that we are going to set up our managers.

from django_ripozo import DjangoManager
from .models import TaskBoard, Task

class TaskBoardManager(DjangoManager):
    # These are the default fields to use when performing any action
    fields = ('id', 'title', 'task_set.id',)
    update_fields = ('title',) # These are the only fields allowed when updating.
    model = TaskBoard
    paginate_by = 10

class TaskManager(DjangoManager):
    fields = ('id', 'title', 'description', 'completed', 'task_board_id',)
    model = Task
    paginate_by = 20

That’s how simple it is to set up our managers.

Creating your resources

Resources are the core of ripozo. These are common across all manager and dispatcher packages. This means, assuming that the application was developed well, you could reuse the resources in flask or mix them in with the sqlalchemy manager.

The first thing we are going to do is create a file in the todoapp directory called resources.py. Then we will add the following

from ripozo import restmixins, ListRelationship, Relationship, apimethod
from .managers import TaskBoardManager, TaskManager

class TaskBoardResource(restmixins.CRUDL):
    manager = TaskBoardManager()
    resource_name = 'taskboard'
    pks = ('id',)
    _relationships = (
        ListRelationship('task_set', relation='TaskResource'),
    )

    # We're going to add a simple way to add
    # tasks to a board by extending the
    @apimethod(route='/addtask', methods=['POST'])
    def add_task(cls, request):
        body_args = request.body_args
        body_args['task_board_id'] = request.get('id')
        request.body_args = body_args
        return TaskResource.create(request)

class TaskResource(restmixins.CRUD):
    manager = TaskManager()
    resource_name = 'task'
    pks = ('id',)
    _relationships = (
        Relationship('task_board', property_map=dict(task_board_id='id'), relation='TaskBoardResource'),
    )

We now have a reusable core to our RESTful API. This is reusable across various web frameworks, databases (you will have to change the manager), or REST protocol.

Setting up your dispatcher.

The dispatcher is responsible for translating the request into something that the framework (Django) can understand and translating the ripozo response into the frameworks preferred method. First create a urls.py file in your todoapp directory. In that file:

from django_ripozo import DjangoDispatcher
from ripozo.adapters import SirenAdapter, HalAdapter
from .resources import TaskBoardResource, TaskResource

dispatcher = DjangoDispatcher(base_url='/api')
dispatcher.register_resources(TaskBoardResource, TaskResource)
dispatcher.register_adapters(SirenAdapter, HalAdapter)

urlpatterns = dispatcher.url_patterns

And right there you’ve set up your url patterns and registered the resources with the application.

Using the api

We’ll be using pypermedia to access the api. It makes it extremely easy to use a SIREN based protocol. You could use HAL protocol if you preferred by prepending that to your accept-types.

pip install pypermedia

First we’ll create a task board

>>> siren_client = HypermediaClient.connect('http://127.0.0.1:5000/api/taskboard/', request_factory=requests.Request)
>>> task_board_list = siren_client.retrieve_list()
>>> created = task_board_list.create(title='My First Board')
>>> retrieve = created.retrieve()
>>> print(created.title)
'My First Board'
>>> print(created.id)
5

Now we can update the board’s title.

>>> updated = retrieve.update(title='My Updated Board')
>>> print(updated.title)
'My Updated Board'

Of course we can’t have a task board without any tasks!

>>> new_task = updated.add_task(title='My first task', description='I need to do something')
>>> print(new_task.title)
'My first task'
>>> print(new_task.description)
'I need to do something'
>>> print(new_task.completed)
False

We can now get this task from the task board itself.

>>> task_board = retrieve.retrieve()
>>> task = next(task_board.get_entities('tasks'))
>>> print(task.description)
'I need to do something'
>>> print(task.completed)
False

Well I guess we did something. We’ll update the task.

>>> task = task.update(completed=True)
>>> print(task.completed)
True

And we can get the board this task belonds to by getting the task_board entity

>>> parent_board = next(task.get_entities('task_board'))
>>> print(parent_board.title)
'My Updated Board'

That task is dumb. Let’s delete it.

>>> deleted = task.delete()
>>> original_task = task.retrieve()
>>> print(original_task)
None