Django Declarative APIs v0.31

Overview

django-declarative-apis is a framework built on top of Django aimed at teams implementing RESTful APIs. It provides a simple interface to define endpoints declaratively. Some benefits to using django-declarative-apis:

  • Define endpoints declaratively

  • Define model-bound and unbound resource endpoints with a consistent interface

  • OAuth 1.0a authentication out of the box

  • Define resource and endpoint-bound tasks, promoting modularity

  • Define synchronous and asynchronous tasks (asynchronous tasks implemented with Celery)

  • Separation of concerns between request body processing and business logic

Quick Start

We are going to create a simple todo app that can only add tasks to a todo list.

Project Setup

Create a new project named dda_project and a new app called todo.

# create a new project directory
mkdir dda_todo_app
cd dda_todo_app

# create a virutal environment
python -m venv env
source env/bin/activate

# install django
pip install django

# create a new project
django-admin startproject dda_project
cd dda_project

# create a new app
python manage.py startapp todo
cd ..

Install django-declarative-apis

Clone django-declarative-apis repository.

git clone https://github.com/salesforce/django-declarative-apis.git

Django Config Settings Setup

Add the todo app and django-declarative-apis to the list of installed apps in settings.py.

INSTALLED_APPS = ['django_declarative_apis','todo',]

Add the DDA required configuration to settings.py.

# This will be used later in the process to find the correct EndpointResource.
# The EndpointResource is responsible for authentication and routing of the requests.
DECLARATIVE_ENDPOINT_RESOURCE_ADAPTER = (
    "django_declarative_apis.adapters.EndpointResource"
)

# The authentication handler is used by endpoint resource to authenticate the requester.
DECLARATIVE_ENDPOINT_AUTHENTICATION_HANDLERS = [
(
 (None, 'django_declarative_apis.authentication.oauthlib.oauth1.TwoLeggedOauth1Hint'),
 'django_declarative_apis.authentication.oauthlib.oauth1.TwoLeggedOauth'
 ),
]

# This will be the default filters that will applied to all the endpoint definitions' responses
DECLARATIVE_ENDPOINT_DEFAULT_FILTERS = "todo.filters.TodoResponseFilter"

Models Setup

Let’s set up a Todo model in todo/models.py.

from django.db import models

class Todo(models.Model):
    task                = models.CharField(max_length=255, null=False)
    priority            = models.CharField(max_length=255)
    created_date        = models.DateTimeField(auto_now_add=True)
    completion_status   = models.BooleanField(default=False)

    def __str__(self):
        return f"{self.task}"

Filters Setup

Let’s set up filters in todo/filters.py that will decide the format of the API response.

from django_declarative_apis.machinery import filtering
from .models import Todo

TodoResponseFilter = {
    Todo: {
        'task': filtering.ALWAYS,
        'priority': filtering.ALWAYS,
        'created_date': filtering.ALWAYS,
        'completion_status': filtering.ALWAYS
    },
}

URLs

Let’s set up the URLs in todo/urls.py.

from django.conf.urls import url

urlpatterns = [
       url(
        r"^tasks/$",
        post=resource_adapter(post=resources.TodoUpdateDefinition,)
        ),
]

The important points to note here:

  1. resource_adapter is a helper function that will look into Django’s config settings and find the endpoint resource adapter to call. In our case, DECLARATIVE_ENDPOINT_RESOURCE_ADAPTER is set to EndpointResource, which is the endpoint resource that will be called.

  2. EndpointResource will perform:
    1. Authentication configuration check.

    2. Endpoint binding, which means routing the request to an endpoint definition based on the HTTP verb used and the required parameters accepted by the endpoint definition.

    3. The endpoint binder then executes the authentication checks defined in the endpoint definition, which are is_authorized, is_permitted, and is_valid.

  3. Once the endpoint binding is successful, the request will be routed to the endpoint definition that can handle it. In our case it will be routed to resources.TodoUpdateDefinition.

Note

All of the above-mentioned operations will be handled by the framework and will run in the background.

Resources Setup

Let’s set up our endpoint definition in a new file named todo/resources.py. The endpoint definition is TodoUpdateDefinition that will be used to create a new a task in the todo list.

from django_declarative_apis import machinery
from django_declarative_apis.machinery import field, endpoint_resource
from .models import Todo


class TodoResourceMixin:
    consumer = None
    _consumer_type = None

    def is_authorized(self):
        return True

class TodoUpdateDefinition(TodoResourceMixin, machinery.ResourceUpdateEndpointDefinition):
    task = field(required=True, type=str)
    priority = field(required=True, type=str)
    completion_status = field(type=bool, default=False)

    @endpoint_resource(type=Todo)
    def resource(self):
        task, created = Todo.objects.get_or_create(
            task=self.task,
            priority=self.priority,
            completion_status=self.completion_status,
        )
        return task

The important points to note here:

  1. Once the authentication and binding are successfully completed, the framework will run TodoUpdateDefinition.resource(), which will refer to the fields.

  2. fields will process the request data.

    Note

    If aggregates and tasks are present, the framework will also be process those in this stage.

  3. By default DDA calls TodoUpdateDefinition.response, which returns TodoUpdateDefinition.resource as the response of the endpoint.

    Note

    The default response can be overridden.

  4. The format of the response will be determined by filters.

Note

All of the above-mentioned operations will be handled by the framework and will run in the background.

Contents:

Indices and tables