[Django]-Creating a REST API for a Django application

18👍

Using Tastypie: —

models.py

class User(Document):
    name = StringField()

api.py

from tastypie import authorization
from tastypie_mongoengine import resources
from project.models import *
from tastypie.resources import *

class UserResource(resources.MongoEngineResource):
class Meta:
    queryset = User.objects.all()
    resource_name = 'user'
    allowed_methods = ('get', 'post', 'put', 'delete','patch')
    authorization = authorization.Authorization()

url.py

from tastypie.api import Api
from projectname.api import *

v1_api = Api(api_name='v1')
v1_api.register(UserResource())

Javascript (jQuery)

This example is of a GET request:

$(document).ready(function(){
    $.ajax({
       url: 'http://127.0.0.1:8000/api/v1/user/?format=json',
       type: 'GET',                   
       contentType: 'application/json',
       dataType: 'json',
       processData: false,
       success: function(data){
           alert(data)
       //here you will get the data from server
       },
       error: function(jqXHR, textStatus, errorThrown){
              alert("Some Error")                                  
       }
    })
})

For a POST request, change the type to POST and send the data in proper format

For more details, see the Tastypie docs

👤Kousik

11👍

I’ve used Django REST framework, and in general like how it works. The autogenerated human-browsable API screens are quite handy too.

In theory, it doesn’t mandate any representation format; you define “serializers” that specify which fields and content to expose, and on which serial format. Still, some formats are easier than others. Ultimately, you can add simple function-based views that return the exact JSON object you want. Even in that case, the framework significantly reduces amount of work needed to get a full API.

Like for Django, the best way is to do the whole tutorial at least once, to get a feeling of what goes where. While doing it, don’t yield to the temptation to modify the examples to your specific problems, it only makes things more complicated. After finishing the whole tutorial, you can tell yourself how close the ‘easy’ formats are to your needs.

👤Javier

11👍

Using Django REST Framework

With Django 1.8.4 and DRF 3.3.3.

Here’s a very simple custom JSONSchemaField class you can prop up using Django REST Framework and the jsonschema package (available via pip install jsonschema).

The custom field inherits from DRF’s existing JSONField class with some small changes. It add the step of validating incoming JSON against the JSONSchema definition. If the validation passes, the Django model TextField is used to store/retrieve the raw JSON string.

In app/serializers.py

import json
from rest_framework import serializers
from jsonschema import validate  # validates incoming data against JSONSchema
from jsonschema.exceptions import ValidationError as JSONSchemaValidationError
from .models import Lesson

from .jsonschema import (
    notes_schema,
)


class JSONSchemaField(serializers.JSONField):
# Custom field that validates incoming data against JSONSchema, 
# Then, if successful, will store it as a string.

    def __init__(self, schema, *args, **kwargs):
        super(JSONSchemaField, self).__init__(*args, **kwargs)
        self.schema = schema

    def to_representation(self, obj):
        return json.loads(obj)

    def to_internal_value(self, data):
        try:
            validate(data, self.schema)
        except JSONSchemaValidationError as e:
            raise serializers.ValidationError(e.message)

        return super(JSONSchemaField, self).to_internal_value(json.dumps(data))


class LessonSerializer(serializers.HyperlinkedModelSerializer):
    notes = JSONSchemaField(notes_schema)

    class Meta:
        model = Lesson
        fields = ('url', 'title', 'bpm', 'notes')

In app/models.py

from django.db import models


class Lesson(models.Model):
    created = models.DateTimeField(auto_now_add=True)
    title = models.CharField(max_length=100, blank=True, default='Untitled')
    bpm = models.DecimalField(max_digits=5, decimal_places=2, default=120.00)
    notes = models.TextField()

    class Meta:
        ordering = ('created',)

In app/jsonschema.py

notes_schema = {
    "type": "array",
    "items": {
        "type": "object",
        "properties": {
            "name": {
                "type": "string",
                "pattern": "^[A-G][#b]?[0-9]$"
            },
            "duration": {
                "type": "string",
                "pattern": "^\d+\/\d+$"
            }
        },
        "required": ["name", "duration"]
    }
}

notes_example = [{"name": "C#4", "duration": "1/4"},
                 {"name": "A4", "duration": "1/32"}]

In app/views.py

from rest_framework import viewsets

from .models import Lesson
from .serializers import LessonSerializer


class LessonViewSet(viewsets.ModelViewSet):
    queryset = Lesson.objects.all()
    serializer_class = LessonSerializer
👤jfunk

4👍

Another good combination is Django-Restless, https://django-restless.readthedocs.org/en/latest/, and just building your own serializers within your models. For example

## Models
class Blog(models.Model):
    title = models.CharField()
    user = models.ForeignKey(settings.AUTH_USER_MODEL)
    text = models.TextField()

    def __init__(self, *args, **kwargs):
        self.super().__init__(*args, **kwargs)
        self.schema = { 
            "title" : self.title,
            "text"  : self.text,
            "user"  : self.user.full_name
        }

    @property
    def list_view(self):
        fields = ["title","user"]
        return {key: self.schema[key] for key in fields}

    @property
    def detail_view(self):
        fields = ["title","text","user"]
        return {key: self.schema[key] for key in fields}

## views
from restless.views import Endpoint
from .models import *
class BlogList(Endpoint):
    def get(self, request):
        posts = [blog.list_view for blog in Blog.objects.all()]
        return json.dumps({posts})

and you can add other HTTP verbs as methods as well and use forms for validating this data.

0👍

We use django-piston at the server side to handle REST calls.
It has been severing as quite fine.

[Client] ← REST → [Web-Server]—[Django/django-piston]

Also you can see the response in here as well.

Leave a comment