Create a Django API

Create a Django API

Django is the most popular Python framework. here we going to setup API using Django framework and library TastyPie.

We Expecting you have knowledge about CRUD operations.

Here we going to build a REST-ful API with the CRUD operations, to create, read, update, and delete notes.

Setting Up Our Project

Django divides two parts of projects and apps. Projects contain apps, but apps do not have necessarily belong to a certain project — the idea is to make them reusable across projects.

We’ll only be making one app within one project, but the file structure may seem a little odd if you don’t keep this in mind.

Install Python if you haven’t done so, then let’s install Django and create our project:

pip install Django
django-admin startproject api_django
cd api_django

Now we need to install TastyPie, which will supply us with a REST framework.

 pip install django-tastypie

Finally, we can create our app within our project:

python manage.py startapp api

Within api_django directory, we have two subfolders: one also called api_django, and another named API.

The distinction between the two can be thought of like this: the api_django contains the settings for the configuration of the project, as well as exposing URLs. The api folder handles the actual API magic.

Before we go on, we have to install our app within our project, inside api_django/settings-py:

# api_django/settings.py
INSTALLED_APPS = [
    'django.contrib.admin',
    'django.contrib.auth',
    'django.contrib.contenttypes',
    'django.contrib.sessions',
    'django.contrib.messages',
    'django.contrib.staticfiles',
    'api'
]

Again, our project can have multiple apps installed — and those apps aren’t necessarily to that project. Our project here is api_django, and our app is called api.

With that done, we’re ready to start building.

A Model Start

The first thing we need to create is a Blog model to interact with.

For those unfamiliar with models, this description from the Django docs is as good as any:

A model is the single, definitive source of information about your data. It contains the essential fields and behaviours of the data you’re storing. Generally, each model maps to a single database table.

Django is unique (compared to a framework like Laravel on PHP) in that your migrations follow how you define your models, rather than being separately defined.

We’re going to create our Blog model, and then run our migrations, which will set up our database with a blogs table (with all the appropriate fields).

Let’s create our model, in api/models.py

from django.db import models
# api/models.py
class Blog(models.Model):
    title = models.CharField(max_length=200)
    description = models.TextField()
    created_at = models.DateTimeField(auto_now_add=True)

def __str__(self):
        return '%s %s' % (self.title, self.description)

Okay, our model is all set up. Now to run our migrations, which will set up our database.

python manage.py makemigrations
python manage.py migrate

Let’s go ahead and populate our database with a single note, to make sure all is well:

python manage.py shell
>>> from api.models import Blog
>>> Blog = Blog(title="Top 10 Blog", description="Description Area")
>>> Blog.save()
>>> Blog.objects.all()
<QuerySet [<Blog: Top 10 Blog Description Area>]>
>>> exit()

We create our note, save it, then retrieve all notes. You can see our str method at work, returning both the title and the body.

API-ification

Again, this is a simplified explanation of a complex topic — let’s go ahead and see it in practice:

In your API folder, create a new file called resources.py.

# api/resources.py

from tastypie.resources import ModelResource
from api.models import Blog
class BlogResource(ModelResource):
    class Meta:
        queryset = Note.objects.all()
        resource_name = 'note'

We also name the resource appropriately: ‘note’. This will be important for URLs.
Speaking of which, let’s set those up in our api_django/urls.py file:

from django.conf.urls import url, include
from django.contrib import admin
from api.resources import BlogResource

blog_resource = BlogResource()
urlpatterns = [
    url(r'^admin/', admin.site.urls),
    url(r'^api/', include(blog_resource.urls)),
]

Testing Our API

Finally, we can get running. As in the Node tutorial, we’re going to use Postman to make API requests. You can get it here.

python manage.py runserver

Now in Postman, let’s send a GET request to this URL:

http://localhost:8000/api/blog/1/

Make sure you select JSON from right side drop down there This will set a Content-Type header.

Also, make sure you sending the request to http://localhost:8000/api/blog/, not http://localhost:8000/api/blog. That trailing slash is important since otherwise, Django has to redirect you, losing the POST data.

Send that request and… it fails. We get back a 401, Unauthorized.

TastyPie is protective of its models out of the box, and only allows reading, not modifying, the data.

It’s an easy fix, though — import their basic Authorization class and add it to our resource.

# api/resources.py
from tastypie.resources import ModelResource
from api.models import Blog
from tastypie.authorization import Authorization
class BlogResource(ModelResource):
    class Meta:
        queryset = Blog.objects.all()
        resource_name = 'blog'
        authorization = Authorization()

Now it works! Try the request, and we get back 201.

To double-check, you can send a GET request to http://localhost:8000/api/blog. You should get back both blogs.

All the Endpoints

Okay, so we finished our GET and POST endpoints. What about PUT and DELETE?
Well, the magic of TastyPie is that they’ve already done. Try updating or deleting your first blog by ending PUT or DELETE to http://localhost:8000/api/blog/1/.

It just works!
Just like that, we created a working RESTful API.

Limiting Fields:

If you wanted to only send specific information about a resource, you can limit fields like so.

from tastypie.resources import ModelResource
from api.models import Blog
from tastypie.authorization import Authorization
class BlogResource(ModelResource):
    class Meta:
        queryset = Blog.objects.all()
        resource_name = 'blog'
        authorization = Authorization()
        fields = ['title', 'description']

Now you won’t see our created_at field in any requests.

Leave a Comment