Build a Blog REST API with Django REST Framework
Building a REST API with Django and Dango Rest Framework is so super easy. In this tutorial, we’ll walk through the steps to get your first API up and running.
I am not going to waste your time by writing a lot of details about Django and Django Rest Framework.
Let’s start coding.
Step 1. Create the project directory and navigate to that directory
mkdir blogapi cd blogpai
Step2. Create a virtual environment
python -m venv env
Step3. Activate virtual environment.
. env/bin/activate or source env/bin/activate
Step4. Install Django and Django REST framework into the virtual environment
pip install django pip install djangorestframework
Step5. Create django project
django-admin startproject blogapi
Step6. Create app blogpostapi
cd blogpai python manage.py startapp blogpostapi
Step7. Add your app in Installed app in settings.py file and don’t forget to add rest_framework in installed app.
Application definition
INSTALLED_APPS = [ 'django.contrib.admin', 'django.contrib.auth', 'django.contrib.contenttypes', 'django.contrib.sessions', 'django.contrib.messages', 'django.contrib.staticfiles', 'rest_framework', 'blogpostapi', ]
Step8. Create super user.
python manage.py createsuperuser
Step9. Go to models.py file in your blogpostapi and paste the following code
#models.py in blogpostapi
Follow the link if you want to explore more .
https://docs.djangoproject.com/en/3.1/topics/db/managers/
https://docs.djangoproject.com/en/3.1/ref/models/fields/
from django.db import models
# Create your models here.
from django.utils import timezone
from django.contrib.auth.models import User
class PublishedManager(models.Manager):
def get_queryset(self):
"""
The super() function in Python makes class inheritance more manageable and extensible.
The function returns a temporary object that allows reference to a parent class by the keyword super.
"""
return super().get_queryset().filter(status='published')
class Post(models.Model):
STATUS_CHOICES = (
('draft', 'Draft'),
('published', 'Published'),
)
title = models.CharField(max_length=250)
#unique_for_date parameter to this field so that you can build URLs for posts using their publish date and slug . Django will prevent multiple posts from having the same slug for a given date.
slug = models.SlugField(max_length=250, unique_for_date='publish')
#https://docs.djangoproject.com/en/3.0/ref/models/fields/#django.db.models.ForeignKey.on_delete .
author = models.ForeignKey(User, on_delete=models.CASCADE, related_name='blog_posts')
body = models.TextField()
publish = models.DateTimeField(default=timezone.now)
created = models.DateTimeField(auto_now_add=True)
updated = models.DateTimeField(auto_now=True)
#This field shows the status of a post. You use a choices parameter, so the value of this field can only be set to one of the given choices.
#https://docs.djangoproject.com/en/3.0/ref/models/fields/
status = models.CharField(max_length=10, choices=STATUS_CHOICES, default='draft')
objects = models.Manager() #The default manager.
published = PublishedManager() #Our custom manager.
class Meta:
ordering = ('-publish',)
def __str__(self):
return self.title
Step10. Use the following command to migrate your model.
python manage.py makemigrations python manage.py migrate
Step11. Register your Post model in django admin.
Go to admin.py file in your blogpostapi and register Post Model. This is the simplest way to add Model with django admin.
Follow the link if you want to explore more
https://docs.djangoproject.com/en/3.1/ref/contrib/admin/
from django.contrib import admin # Register your models here. from blogpostapi.models import Post admin.site.register(Post)
Step12. Create an api folder in blogpostapi.
. ├── blogapi │ ├── asgi.py │ ├── __init__.py │ ├── __pycache__ │ │ ├── __init__.cpython-39.pyc │ │ ├── settings.cpython-39.pyc │ │ ├── urls.cpython-39.pyc │ │ └── wsgi.cpython-39.pyc │ ├── settings.py │ ├── urls.py │ └── wsgi.py ├── blogpostapi │ ├── admin.py │ ├── api │ │ ├── __pycache__ │ │ │ ├── serializers.cpython-39.pyc │ │ │ ├── urls.cpython-39.pyc │ │ │ └── views.cpython-39.pyc │ │ ├── serializers.py │ │ ├── urls.py │ │ └── views.py │ ├── apps.py │ ├── __init__.py │ ├── migrations │ │ ├── 0001_initial.py │ │ ├── 0002_auto_20210214_1223.py │ │ ├── 0003_auto_20210214_1235.py │ │ ├── __init__.py │ │ └── __pycache__ │ │ ├── 0001_initial.cpython-39.pyc │ │ ├── 0002_auto_20210214_1223.cpython-39.pyc │ │ ├── 0003_auto_20210214_1235.cpython-39.pyc │ │ └── __init__.cpython-39.pyc │ ├── models.py │ ├── __pycache__ │ │ ├── admin.cpython-39.pyc │ │ ├── __init__.cpython-39.pyc │ │ └── models.cpython-39.pyc │ ├── tests.py │ └── views.py ├── db.sqlite3 └── manage.py
Step13. Create serializers.py , urls.py and views.py under api folder and add the following code.
#serializers.py from rest_framework import serializers from django.contrib.auth import get_user_model from blogpostapi.models import Post class PostSerializer(serializers.ModelSerializer): author = serializers.StringRelatedField(read_only=True,) status = serializers.StringRelatedField(read_only=True) class Meta: model = Post fields = "__all__"
#views.py from blogpostapi.models import Post from blogpostapi.api.serializers import PostSerializer from rest_framework import generics from rest_framework import permissions class PostList(generics.ListAPIView): #queryset = Post.objects.all() serializer_class = PostSerializer def get_queryset(self): """ override the queryset method. """ return Post.objects.filter(status='published') class PostDetail(generics.RetrieveAPIView): #queryset = Post.objects.all() serializer_class = PostSerializer #permission_classes = [permissions.IsAuthenticatedOrReadOnly] def get_queryset(self): """ Override the queryset method. """ return Post.objects.filter(status='published')
#urls.py
from django.urls import path from blogpostapi.api.views import PostDetail, PostList urlpatterns = [ path('posts/', PostList.as_view(), name='posts-list'), path('posts/<int:pk>/', PostDetail.as_view(), name='post-detail'), ]
Now open urls.py file in main project folder and include blogpostapi urls.
#urls.py in blogapi from django.contrib import admin from django.urls import path, include urlpatterns = [ path('admin/', admin.site.urls), path('api/', include('blogpostapi.api.urls')), ]