Django Polls Tutorial API
This tutorial assumes you already have Python3 and pipenv installed. You can find detailed instructions here.
Complete source code is available on Github.
To start we need to create a new directory for our code, install Django and Django Rest Framework, make a new project
mysite and then a new app
$ cd polls && cd polls $ pipenv install django djangorestframework $ pipenv shell (polls) $ django-admin startproject mysite . (polls) $ python manage.py startapp polls
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.
# mysite/settings.py ... INSTALLED_APPS = [ ... 'rest_framework', 'polls', ] TIME_ZONE = 'America/New_York'
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
Now we need to set our urls. We’ll place our polls content at
api/ as follows.
# mysite/urls.py from django.urls import include, path from django.contrib import admin urlpatterns = [ path('api/', include('polls.urls')), path('admin/', admin.site.urls), ]
polls app we need to create
(polls) $ touch polls/urls.py (polls) $ touch polls/serializers.py
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, base_name='questions') urlpatterns = router.urls
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
And our view will expose everything for now with DRF’s
# 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
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
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)
Then create a
superuser account and start the local server.
$ python manage.py createsuperuser $ python manage.py runserver
Now navigate to http://127.0.0.1:8000/admin to login.
Add a new questions by clicking on “+ Add” next to Questions.
Then add a Choice option by clicking on “+ Add” next to Choices on the admin homepage.
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.
Interested in learning more Django? I’ve written 3 books!