DEV Community

Will Vincent for Learn Django

Posted on • Originally published at learndjango.com

Django Polls Tutorial API

The polls tutorial is the official guide to Django. As a fun exercise, I wanted to show how little code it takes to transform it into a robust API using Django Rest Framework.

This tutorial assumes you already have Python3 and pipenv installed. You can find detailed instructions here.

Installation

To start we need to create a new directory for our code, install Django and Django Rest Framework, make a new project config and then a new app polls.

$ mkdir polls && cd polls
$ pipenv install django djangorestframework
$ pipenv shell
(polls) $ django-admin startproject config .
(polls) $ python manage.py startapp polls
Enter fullscreen mode Exit fullscreen mode

Update our settings.py file with our new apps and also adjust the timezone since each poll is timestamped. I'm based on the east coast of the U.S. so my timezone is New_York. Here is a list of all timezones.

# config/settings.py
...
INSTALLED_APPS = [
    ...
    'rest_framework',
    'polls',
]

TIME_ZONE = 'America/New_York'
Enter fullscreen mode Exit fullscreen mode

The only code that carries over from the original polls tutorial is the database model. Here it is for a Question and then a related Choice.

# polls/models.py
import datetime

from django.db import models
from django.utils import timezone

class Question(models.Model):
    question_text = models.CharField(max_length=200)
    pub_date = models.DateTimeField('date published')

    def was_published_recently(self):
        now = timezone.now()
        return now - datetime.timedelta(days=1) <= self.pub_date <= now

    def __str__(self):
        return self.question_text


class Choice(models.Model):
    question = models.ForeignKey(Question, on_delete=models.CASCADE)
    choice_text = models.CharField(max_length=200)
    votes = models.IntegerField(default=0)

    def __str__(self):
        return self.choice_text
Enter fullscreen mode Exit fullscreen mode

Now we need to set our urls. We'll place our polls content at api/ as follows.

# config/urls.py
from django.urls import include, path
from django.contrib import admin

urlpatterns = [
    path('api/', include('polls.urls')),
    path('admin/', admin.site.urls),
]
Enter fullscreen mode Exit fullscreen mode

Within the polls app we need to create urls.py and serializers.py files.

(polls) $ touch polls/urls.py
(polls) $ touch polls/serializers.py
Enter fullscreen mode Exit fullscreen mode

For the polls/urls.py file we'll be using viewsets to simplify the code.

# polls/urls.py
from django.urls import path

from .views import QuestionViewSet
from rest_framework.routers import DefaultRouter

router = DefaultRouter()
router.register('', QuestionViewSet, basename='questions')
urlpatterns = router.urls
Enter fullscreen mode Exit fullscreen mode

Our serializer exposes all fields plus the id field Django automatically adds for us.

# polls/serializers.py
from rest_framework import serializers
from .models import Question


class QuestionSerializer(serializers.ModelSerializer):
    class Meta:
        fields = (
            'id',
            'question_text',
            'pub_date',
        )
        model = Question
Enter fullscreen mode Exit fullscreen mode

And our view will expose everything for now with DRF's ModelViewSet.

# polls/views.py
from rest_framework import viewsets

from . import models
from . import serializers


class QuestionViewSet(viewsets.ModelViewSet):
    queryset = models.Question.objects.all()
    serializer_class = serializers.QuestionSerializer
Enter fullscreen mode Exit fullscreen mode

As a last step we need to make a new migrations file and migrate our database changes.

(polls) $ python manage.py makemigrations polls
(polls) $ python manage.py migrate
Enter fullscreen mode Exit fullscreen mode

We're done! That's it. We now have a functioning, complete API for the polls tutorial. But we haven't populated it with any content. In the polls tutorial they do this in the Django shell, but I find the Django admin to be much easier to work with. First update our admin.py file so the polls app appears.

# polls/admin.py
from django.contrib import admin

from .models import Question
from .models import Choice

admin.site.register(Question)
admin.site.register(Choice)
Enter fullscreen mode Exit fullscreen mode

Then create a superuser account and start the local server.

$ python manage.py createsuperuser
$ python manage.py runserver
Enter fullscreen mode Exit fullscreen mode

Now navigate to http://127.0.0.1:8000/admin to login.

Admin

Add a new questions by clicking on "+ Add" next to Questions.

Admin Question

Then add a Choice option by clicking on "+ Add" next to Choices on the admin homepage.

Admin choice

Now we can navigate to our actual API for which DRF provides a nice graphical view of both the list view at http://127.0.0.1:8000/api/ and detail view at http://127.0.0.1:8000/api/1/.

API list view

API detail view

Next Steps

The official polls tutorial can be overwhelming for beginners but at the end of the day there's not much code involved. And thanks to the power of DRF we can create web APIs with a shockingly small amount of code, yet still have the flexibility to change things as needed.

Top comments (4)

Collapse
 
francelwebdev profile image
Francel

Hello, I am familiar with ruby and rails. I learned the basics of python and django and I want to do some stuff in django like saving data to two different tables at the same time with a single form on the page like I do in ruby on rails with nested_attribute and field_for. Please how do we do that. Also how to send a javascript response to the browser as I do in rails with respond_to do | format | . Thank you.

Collapse
 
wsvincent profile image
Will Vincent

You probably want to check out Django REST Framework for API/JavaScript things with Django. It's a 3rd party package but basically part of Django itself. Here's a tutorial on it: learndjango.com/tutorials/django-r....

For forms..I don't have a specific tutorial on that but Matt Layman did a nice recent overview: mattlayman.com/understand-django/u...

Collapse
 
xarala221 profile image
Ousseynou Diop

Thank you.

Collapse
 
wsvincent profile image
Will Vincent

You're welcome! Thanks for taking the time to comment.