Back
Feb 28, 2017

How to write an API in Django

Introduction

There is such a term as Remote Procedure Call (RPC). In other words, by using this technology, programs can call functions on remote computers. There are many ways to implement RPC. Here are some of them related to web technologies and this is what we will focus on:

Each of these technologies can be used in Django. In this article we will look at the libraries which add RPC support for Django.

REST

Let's start with the most common protocol - REST. REST stands for Representational State Transfer - transfer of the state representation. In fact, REST is an architectural style, not the protocol. For example, SOAP is a protocol. Due to its popularity and prevalence there is a large selection of libraries for Django which allow you to turn your views into REST views by making simple actions.

In the world of Django REST API there are a few of the most popular libraries, and we will compare them. In comparison table I have identified the most important factors, in my opinion, that are relevant when choosing the library.

 Django REST frameworkTastypiePistonDjango XML-RPCDjango REST Pandas
Version3.5.3 (Production/Stable)0.13.3 (Beta)0.2.3 (Alpha)0.1.7 (Production/Stable)0.5.0 (Production/Stable)
Python 3 supportYesYesNoYes0Yes
Repositorydjango-rest-frameworkdjango-tastypiedjango-pistondjango-xmlrpcdjango-rest-pandas
Stars7107312896248379
Forks243210813041531
Documentationdjango-rest-framework.orgdjango-tastypie.readthedocs.io/en/latest/bitbucket.org/jespern/django-piston/wiki/Documentationgithub.com/Fantomas42/django-xmlrpcgithub.com/wq/django-rest-pandas
API key authenticationYesYesNo--
OAuthYesYesNo--
OAuth2YesYesNo--
Accept HeadersYesYesNo-via DRF
SerializationsJSON, JSONp, XML, YAML, HTML, MessagePack, CSVJSON, JSONp, XML, YAML, HTML, plistXML, JSON, YAML, Pickle, Django-CSV, TXT, XLS, XLSX, JSON, PNG, SVG

So, we can summarize, if your API architecture is complex (mobile devices support, versioning, Mongo models serialization), it is better to choose Django REST framework. Tastypie and Piston can be used for small, simple projects.

SOAP

Nowadays, REST is the most popular. But there may be situations when you need to have an interface for legacy products. The library, which adds SOAP support in django, is called spyne. Let's see how this works in django. First, install the pip install spyne package and add 'rpctest.core' into INSTALLED_APPS.

views.py

import logging
logging.basicConfig(level=logging.DEBUG)

from spyne import Application, rpc, ServiceBase, Integer, Unicode
from spyne import Iterable
from spyne.protocol.http import HttpRpc
from spyne.protocol.soap import Soap11
from spyne.server.django import DjangoApplication

from django.views.decorators.csrf import csrf_exempt


class HelloWorldService(ServiceBase):
    @rpc(Unicode, Integer, _returns=Iterable(Unicode))
    def say_hello(ctx, name, times):
        for i in range(times):
            yield 'Hello, %s' % name


application = Application([HelloWorldService],
    tns='spyne.examples.hello',
    in_protocol=HttpRpc(validator='soft'),
    out_protocol=Soap11()
)


hello_app = csrf_exempt(DjangoApplication(application))

urls.py

from django.conf.urls import url

from spyne.protocol.soap import Soap11
from spyne.server.django import DjangoView

from hello.views import hello_app, application, HelloWorldService


urlpatterns = [
    url(r'^hello_world/', hello_app),
    url(r'^say_hello/', DjangoView.as_view(
        services=[HelloWorldService], tns='spyne.examples.hello',
        in_protocol=Soap11(validator='lxml'), out_protocol=Soap11())),
    url(r'^say_hello_not_cached/', DjangoView.as_view(
        services=[HelloWorldService], tns='spyne.examples.hello',
        in_protocol=Soap11(validator='lxml'), out_protocol=Soap11(),
        cache_wsdl=False)),
    url(r'^api/', DjangoView.as_view(application=application)),
]

Let's make a curl request to check our test application:

curl "http://localhost:8000/say_hello?name=World×=4" | tidy -q -xml -indent -wrap 0

As a result, the output we get:

<?xml version='1.0' encoding='utf-8'?>
<senv:Envelope xmlns:tns="spyne.examples.hello"
      xmlns:senv="http://schemas.xmlsoap.org/soap/envelope/">
  <senv:Body>
    <tns:say_helloResponse>
      <tns:say_helloResult>
        <tns:string>Hello, World</tns:string>
        <tns:string>Hello, World</tns:string>
        <tns:string>Hello, World</tns:string>
        <tns:string>Hello, World</tns:string>
      </tns:say_helloResult>
    </tns:say_helloResponse>
  </senv:Body>
</senv:Envelope>

As you can see, there is nothing complicated, spyne library does all the work. Spyne has a lot of settings, for example, if it is necessary to get JSON instead of XML as a response from the API, it is done as follows:

from spyne.protocol.json import JsonDocument


application = Application([HelloWorldService],
    tns='spyne.examples.hello',
    in_protocol=HttpRpc(validator='soft'),
    out_protocol=JsonDocument()
)

Now the response from the API will be rendered in JSON

curl "http://localhost:8000/say_hello?name=World×=4" | python -m json.tool
[
    "Hello, World",
    "Hello, World",
    "Hello, World",
    "Hello, World"
]

Apart from Django, spyne.io supports Twisted and Pyramid.

Protocol Buffers

Protocol Buffers is a new serialization protocol, which was proposed by Google as XML replacement. As Google claims, buffers protocol is easier, faster and smaller than XML. Officially, there is support for C ++, C #, Go, Java and Python. Other languages are supported by third-party developers.

The first thing you need is to create .proto file, where the structure will be described.

message Person {
  required string name = 1;
  required int32 id = 2;
  optional string email = 3;

  enum PhoneType {
    MOBILE = 0;
    HOME = 1;
    WORK = 2;
  }

  message PhoneNumber {
    required string number = 1;
    optional PhoneType type = 2 [default = HOME];
  }

  repeated PhoneNumber phones = 4;
}

In our example, the Person object is described: it has two mandatory fields - id/name, one optional field - email, and PhoneNumber field, which can contain user’s multiple phone numbers.

When .proto is created, it should be compiled. This is done with help of protobuf library.

protoc -I=$SRC_DIR --python_out=$DST_DIR $SRC_DIR/person.proto

After compiling person_pb2.py file will be created.

class Person(message.Message):
    metaclass = reflection.GeneratedProtocolMessageType
  
    class PhoneNumber(message.Message):
        metaclass = reflection.GeneratedProtocolMessageType
        DESCRIPTOR = _PERSON_PHONENUMBER
  
    DESCRIPTOR = _PERSON

Now imagine that we have a view, which shows information about the user. As an example, I will use the simplest way to show how Protocol Buffer can work in Django.

import person_pb2


def person_info(request):
    person = person_pb2.Person()
    person.id = 1
    person.name = "Luke Skywalker"
    person.email = "luke@skywalker.com"
    phone = person.phones.add()
    phone.number = "123-8794"
    phone.type = person_pb2.Person.HOME
    return HttpResponse(person.SerializeToString(), content_type="application/octet-stream")

GraphQL

In 2015, Facebook introduced a new standard in the public declaration of data structures and methods of obtaining data - GraphQL. Among the main features of GraphQL we can point out the next ones:

  • strong typing
  • interface support
  • documented representation of the circuit in the form of data structures
  • independence from the version of the server API

For more information about GraphQL you can read the articles of my colleagues in our blog How to Use GraphQL with Django and How to Use GraphQL with Angular 2.

Conclusion

As you can see from the article, among all the technologies for API implementation in Django, REST leads by the number of libraries. The popularity of REST is characterized by its simplicity and functionality. It is also important to note that the data is transmitted without the use of additional layers, so REST is considered to be less resource-intensive, unlike SOAP or XML-RPC. But it also has disadvantages, like any other technology. When you select a backend for the API, be guided by your needs rather than popularity.

Subscribe for the news and updates

More thoughts
Apr 11, 2024Technology
Test Analysis at the Feature Level

In the previous article, we learned about test analysis for a product in general, and now we are ready to go further and look at test analysis for specific features.

Mar 18, 2024Technology
From boring to exciting: turn learning to code into an adventure

Tired of boring programming courses where you're forced to read thick textbooks and write code that's never used? Need a platform that makes learning fun and exciting? Then you're in the right place!

Sep 8, 2023Technology
Smooth React virtual scroll with fixed rows/columns

One of our ongoing projects, Neptyne, introduces an Excel-like grid written in React. We used a library to apply virtual scroll to it, but we stumbled upon a problem with fixed rows and columns inside the grid. Here I would like to describe this problem, how it occurs, and how we handled it.

Jul 13, 2022Technology
Prosemirror: Render node as react component

In this article I’m going to show how to declare custom prosemirror node, how to render it with toDom method and how improve that with custom NodeView using React component.

Dec 1, 2016Technology
How to Use Django & PostgreSQL for Full Text Search

For any project there may be a need to use a database full-text search. We expect high speed and relevant results from this search. When we face such problem, we usually think about Solr, ElasticSearch, Sphinx, AWS CloudSearch, etc. But in this article we will talk about PostgreSQL. Starting from version 8.3, a full-text search support in PostgreSQL is available. Let's look at how it is implemented in the DBMS itself.

Jul 1, 2010Technology
Overriding QuerySet in Django

As you know, model managers can be overriden in Django. It's convenient to add custom filtration method.