A Crash Course in Django

A Crash Course in Django

<br>


Originally published by Ari Birnbaum at Ceiphr on April 21

Prerequisites

Basic PythonHTMLCSS and Unix Command Line. As long as you're comfortable with all that, you're good.


Table of Contents
  1. Introduction
  2. Our Goal
  3. So what is Django?
  4. Setting up our project
  5. The Database
  6. Media file support
  7. Writing our models
  8. Migrating our new models
  9. Admin control panel
  10. View logic
  11. Templates with Style
  12. Wrap Up 
Introduction

This is not a tutorial. This crash course is a quick way to get started making a basic Django website without going in-depth about the underlying concepts that are required to make complex web applications. For every step of this crash course I will link a more thorough explanation of the tools and concept you're using so you can get a better understanding of Django while creating your first project.

Our Goal

We're making a website where you can upload an image with a title, date and description. Simple.

So what is Django?

Django /JANG-oh/ — A type of tool (web framework) most known for helping people make neat websites quickly with few mistakes.

Making stuff in Django follows this pattern:

  1. Model — How you store stuff. This is where we will tell Django how to store our images, titles, dates and descriptions.
  2. View — Where your project thinks. This is how our website will get the stuff we stored based on our models and process it for the user.
  3. Template — How your project presents the stuff it was thinking about. The view will use this to display the contents it processed based on our models.

Django does more complex (and really fun) things, but if you're starting out that's all you need to know for now.

[in-depth]

Setting up our project

NOTICE: Windows Users

By default, Windows doesn't have a Unix command line, which is a prerequisite for this crash course. The October 2018 update for Windows 10 offers Linux subsystems, such as Ubuntu. Please install and set up a Linux subsystem to utilize the Unix command line.

We're going to use your computer's terminal to set up our python environment and Django. Let's make the project in our computer's Documents folder, so enter these commands

$ cd ~/Documents
$ python3 -m venv django_cc
  • python3 -m venv django_cc will create a virtual environment within a folder called django_cc for our project so all the stuff we install for it to work won't interfere with anything else on your system. [in-depth]

Next we'll get in our project folder, enable our new python environment and install Django.

$ cd django_cc
$ source bin/activate
$ pip install django
  • source bin/activate will activate the virtual environment we created. This means when we install Django, it won't be installed on the whole system, just in our project.
  • pip install django will use Python's package manager to install the most recent version of Django.

Now that Django is installed we get some new commands. Let's start by creating a project within Django, migrating our development database and finally starting our local development server for the first time to ensure we did everything right.

$ django-admin startproject django_cc
$ cd django_cc
$ python3 manage.py migrate
$ python3 manage.py runserver
  • django-admin start project django_cc is telling django to make the stem of our project where everything else will be connected (i.e. django apps). [in-depth]
  • This is also where we will find manage.py the file that we will use to interact with Django.
  • python3 manage.py migrate is used to let Django know that changes have been made to our models. Since we've just started our project this will be our initial migration which establishes models Django makes on its own (i.e. accounts, activity logs, permissions, etc.). [in-depth]
  • python3 manage.py runserver will start our development server where we will be testing our project.

To see the development server in action go to 127.0.0.1:8000 in your browser. A Django start up page should appear:

The Database

Next grab your favorite text editor or python IDE because we're going to delve into Django. We're going to start by creating a Django app where we will write all of our models for this project.

$ python manage.py startapp database

In order for our core project to recognize this app we need to let it know our database app exists by adding it to INSTALLED_APPS in django_cc/settings.py like so:

# Application definition

INSTALLED_APPS = [
'django.contrib.admin',
'django.contrib.auth',
'django.contrib.contenttypes',
'django.contrib.sessions',
'django.contrib.messages',
'django.contrib.staticfiles',
'database',
]

Media file support

Let's add the following to the bottom of settings.py so Django knows where to store media files such as the images that we upload:

# Media file support

MEDIA_ROOT = os.path.join(BASE_DIR, 'media')
MEDIA_URL = '/media/'

We will also need to add a few imports and a conditional at the bottom of django_cc/urls.py so the files are accessible on the development server:

from django.conf.urls import url
from django.contrib import admin

Add these imports for static file support and to get directory details from Django's settings.py

from django.conf.urls.static import static
from django.conf import settings

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

Add this to enable media file support on the development server

if settings.DEBUG:
urlpatterns += static(settings.MEDIA_URL, document_root=settings.MEDIA_ROOT)

[in-depth]

Great, our project is now set up, and we can begin by writing our models.

Writing our models

Inside of our new database app we will find a models.py file where we will write our models for our database. The class Post will act as our first model for uploading a post with an image, title, description, and date published.

from django.db import models
import datetime

class Post(models.Model):
image = models.FileField(upload_to='images/')
title = models.CharField(default="", max_length=64)
description = models.CharField(default="", max_length=512)
date = models.DateField(default=datetime.date.today)

  • models.FileField(upload_to='images/') acts as a field where we will upload images to an image folder in the media directory we configured in settings.
  • models.CharField(default="", max_length=n) is a basic text field where the max character length is n.
  • models.DateField(default=datetime.date.today) is self explanitory, it's a date/time field that is set to the current date and time.

[in-depth]

To finish off our models let's tell Django to order them based newest to oldest:

class Post(models.Model):
image = models.FileField(upload_to='images/')
title = models.CharField(default="", max_length=64)
description = models.CharField(default="", max_length=512)
date = models.DateField(default=datetime.date.today)
class Meta:
ordering = ['-date']
def str(self):
return self.title
  • The Meta class can do a lot, in our case we will use it to order our models based on time.
  • The str function is telling Django to display the title (instead of saying Post 1, Post 2, etc.) for when we interact with our entries later on in the Django admin panel.

[in-depth]

Migrating our new models

Finish off our models with the following two commands that essentially tell Django that we've made some changes and that they should be applied to our database:

$ python3 manage.py makemigrations
$ python3 manage.py migrate

Congratulations! Our database is all set up for our posts. There is one issue though. We can't edit them right now. Let's get you set up with the Django admin panel so you make some posts.

Admin control panel

Inside of our database app go to admin.py and add the following:

from django.contrib import admin
from database.models import *

admin.site.register(Post)

  • from database.models import Post imports all the models that we've just created.
  • admin.site.register(<model_name>) tells Django to display that model within the control panel.

Next we will create a superuser, so we can log into the admin panel. Type the following command and follow the prompts. You only need to fill out the username and passwords prompts.

$ python3 manage.py createsuperuser
Username (leave blank to use 'ari'):
Email address:
Password:
Password (again):
Superuser created successfully.

Once completed head over to 127.0.0.1:8000/admin and sign in with the credentials you just wrote. You should see this page:

From here you can add posts to your Django project. We are officially done with our models. Next will design our view so Django can serve our posts.

View logic

A view is how Django knows what to do when we ask for a page. The first thing we have to do is create a views.py file in django_cc. In that file paste the following:

from django.shortcuts import render
from django.views.generic.base import View
from django.views.generic import TemplateView
from database.models import Post

class post_feed(TemplateView):
template_name = 'index.html'

def get_context_data(self, *args, **kwargs):
    context = dict()
    context["posts"] = Post.objects.all()

  • from django.views.generic import TemplateView allows us to use Django's basic template view which is all that we need for displaying our posts.
  • from database.models import Post imports all of our database models for our view functions to use.
  • post_feed is our basic template view that will use an index.html file we will create next to render our database contents.
  • get_context_data is how we will send our template the information from the database.
  • context["posts"] = Post.objects.all() Our template will refer to posts within our context dictionary for a list of all posts that is collected from the database using Post.objects.all()

[in-depth]

In urls.py we will need to add a new path so Django knows when that URL is requested to call our view:

from django.conf.urls import url
from django.contrib import admin
from django.conf.urls.static import static
from django.conf import settings

import path for easy urls

from django.urls import path

import our views so urls.py can call them

from django_cc.views import post_feed

urlpatterns = [

# Path for root of our website that will display the post feed
path('', post_feed.as_view(template_name="index.html"), name="post_feed"),
url(r'^admin/', admin.site.urls),

]

if settings.DEBUG:
urlpatterns += static(settings.MEDIA_URL, document_root=settings.MEDIA_ROOT)

Our basic view logic is now complete, now we need to build our index template for displaying our posts.

Templates with Style

In the root of our Django project where you can find our database and django_cc folders create a templates folder and make an index.html file inside. For the design of our site we're going to use the framework Bulma so we won't need to write any CSS. Here is a boilerplate we can use for our template.

<!DOCTYPE html>
<html lang="en">
<head>
<title>Posts | Django Crash Course</title>
<link rel="stylesheet"
href="https://cdnjs.cloudflare.com/ajax/libs/bulma/0.7.4/css/bulma.min.css"
integrity="sha256-8B1OaG0zT7uYA572S2xOxWACq9NXYPQ+U5kHPV1bJN4="
crossorigin="anonymous" />
</head>
<body>
</body>
</html>

Django templates utilize a DRY version of HTML called Django HTML. This is how we will send our context to render in our index.html template. In the body of the boilerplate let's add a basic card with the context for our posts.

<div class="container">
{% for post in posts %}
<div class="card">
<div class="card-image">
<figure class="image">
<img src="{{ post.image.url }}" alt="Placeholder image"
style="max-width: 250px; max-height: 250px;">
</figure>
</div>
<div class="card-content">
<div class="content">
<b>{{ post.title }}</b> | {{ post.description }}
<br>
<time datetime="{{ post.date }}">{{ post.date }}</time>
</div>
</div>
</div>
{% endfor %}
</div>
  • {% for post in posts %} acts as a for loop that will duplicate its contents for each post inside posts.
  • Every time the for loop runs the context for the post in the current iteration is placed in the HTML when it is referred to using {{ <variable> }}
  • {{ post.image.url }} is how you refer to the image's URL, you cannot just reference the image itself.

When we visit 127.0.0.1:8000 there should be a list of all the posts we've added in the control panel:

Now we have a website that displays what we add to our control panel in Bulma cards. Neat.

[in-depth]

Wrap Up

Django is a wonderful framework for building websites and other complex things. Today you've created a very basic website that is capable of displaying posts akin to Instagram and in the future hopefully you can build Instagram yourself. For now I suggest learning more about Django either through their documentation or this introduction (which got me started).

FYI — Follow this tutorial by Digital Ocean so you can learn how to host your Django creations for the world to see. If you want to host with Digital Ocean, use my referral link for a discount.

---------------------------------------------------------------

Thanks for reading :heart: If you liked this post, share it with all of your programming buddies! Follow me on Facebook | Twitter

Learn More

☞ Machine Learning with Python, Jupyter, KSQL and TensorFlow

☞ Introduction to Python Microservices with Nameko

☞ Comparing Python and SQL for Building Data Pipelines

☞ Python Tutorial - Complete Programming Tutorial for Beginners (2019)

☞ Python and HDFS for Machine Learning

☞ Build a chat widget with Python and JavaScript

☞ Complete Python Bootcamp: Go from zero to hero in Python 3

☞ Complete Python Masterclass

☞ Learn Python by Building a Blockchain & Cryptocurrency

☞ Python and Django Full Stack Web Developer Bootcamp

☞ The Python Bible™ | Everything You Need to Program in Python

☞ Learning Python for Data Analysis and Visualization

☞ Python for Financial Analysis and Algorithmic Trading

☞ The Modern Python 3 Bootcamp

Python Django Tutorial | Django Course

Python Django Tutorial | Django Course

🔥Intellipaat Django course: https://intellipaat.com/python-django-training/ 👉This Python Django tutorial will help you learn what is django web development &...

This Python Django tutorial will help you learn what is django web development & application, what is django and introduction to django framework, how to install django and start programming, how to create a django project and how to build django app. There is a short django project as well to master this python django framework.

Why should you watch this Django tutorial?

You can learn Django much faster than any other programming language and this Django tutorial helps you do just that. Our Django tutorial has been created with extensive inputs from the industry so that you can learn Django and apply it for real world scenarios.

Developing Restful APIs with Python, Django and Django Rest Framework

Developing Restful APIs with Python, Django and Django Rest Framework

This article is a definitive guide for starters who want to develop projects with RESTful APIs using Python, Django and Django Rest Framework.

This article is a definitive guide for starters who want to develop projects with RESTful APIs using Python, Django and Django Rest Framework.

Introduction
  • Django is a web framework written in Python
  • Python is an interpreted high-level programming language for general-purpose programming
  • API or Application Programming Interface is a set of rules and mechanisms by which one application or component interacts with the others
  • REST or Representational State Transfer is a software architecture

REST APIs

As described in a dissertion by Roy Fielding,

REST is an "architectural style' that basically exploits the existing technology and protocols of the web.
In simple definition, it is the data representation for a client in the format that is suitable for it.

Hence, RESTful + API is a commonly used terminology for the implementation of such architecture and constraints (eg. in web services).

Here is an example GET request from GitHub's API

$ curl https://api.github.com/users/joshuadeguzman

You will see an output similar to this

{
  "login": "joshuadeguzman",
  "id": 20706361,
  "node_id": "MDQ6VXNlcjIwNzA2MzYx",
  "avatar_url": "https://avatars1.githubusercontent.com/u/20706361?v=4",
  "gravatar_id": "",
  "url": "https://api.github.com/users/joshuadeguzman",
  "html_url": "https://github.com/joshuadeguzman",
  "followers_url": "https://api.github.com/users/joshuadeguzman/followers",
  "following_url": "https://api.github.com/users/joshuadeguzman/following{/other_user}",
  "gists_url": "https://api.github.com/users/joshuadeguzman/gists{/gist_id}",
  "starred_url": "https://api.github.com/users/joshuadeguzman/starred{/owner}{/repo}",
  "subscriptions_url": "https://api.github.com/users/joshuadeguzman/subscriptions",
  "organizations_url": "https://api.github.com/users/joshuadeguzman/orgs",
  "repos_url": "https://api.github.com/users/joshuadeguzman/repos",
  "events_url": "https://api.github.com/users/joshuadeguzman/events{/privacy}",
  "received_events_url": "https://api.github.com/users/joshuadeguzman/received_events",
  "type": "User",
  "site_admin": false,
  "name": "Joshua de Guzman",
  "company": "@freelancer",
  "blog": "https://joshuadeguzman.me",
  "location": "Manila, PH",
  "email": null,
  "hireable": true,
  "bio": "Android Engineer at @freelancer. Building tools for humans.",
  "public_repos": 75,
  "public_gists": 2,
  "followers": 38,
  "following": 10,
  "created_at": "2016-07-28T15:19:54Z",
  "updated_at": "2019-06-16T10:26:39Z"
}

Shown above is a data set in JSON format.

JSON or JavaScript Object Notation is an open-standard file format that uses human-readable text to transmit data objects consisting of attribute–value pairs and array data types.
Other formats include XML, INI, CSV, etc. But today, JSON is widely use for its structure is intuitive, making it comfortable to read and map domain objects no matter what programming language is being used.

Python and Django

Python, according to its creator, Guido van Rossum, is a

high-level programming language, and its core design philosophy is all about code readability and a syntax which allows programmers to express concepts in a few lines of code.
Python uses english like words representation (eg. for methods, reserve keywords and control flow) that makes it easier for any beginner to jump right into it. It also features dynamic type system meaning it verifies the type safety of program at runtime. It also does automatic memory management.

print(5 + 5) # This will result to 10

Django is a high-level Python Web Framework that enables developers to deliver projects on time with clean and pragmatic design.

Its flagship features include a design for fast development, a secure and scalable product.

Quick Django Overview

Django's way of propagating changes to your database schema is by means of its migration modules.

Sample User model

from django.db import models

class User(models.Model):
    first_name = models.CharField(max_length=50)
    middle_name = models.CharField(max_length=50)
    last_name = models.CharField(max_length=50)

    def __str__(self):
        return self.name

If any changes are made on your models, run makemigrations

$ python manage.py makemigrations

Finally, you can synchronize the database with the set of models and migrations

$ python manage.py migrate

REST APIs with Django Rest Framework

DRF or Django REST Framework is a powerful and flexible toolkit for building Web APIs. It helps the developers to not reinvent the wheel by rolling out complex and solid REST API from scratch by themselves. Because when your projects become more and more complex, you will soon realise the need of using DRF or other helpful rest framework.

1. Installation & Project Setup

Create project directory

$ mkdir djangoapi

Install virtualenv via pip

A virtual environment enables a project to have additional libraries or changes in packages within its environment without disturbing global or libraries of other environments.

pip is a package management system used to install and manage software packages written in Python.

$ pip install virtualenv

To create an environment folder in your project's directory

$ cd djangoapi
$ virtualenv venv

To activate the environment

$ source venv/bin/activate

To undo these changes to your path, simply run deactivate. More on virtualenv.

Install django, djangorestframework

$ pip install django
$ pip install djangorestframework

Creating a django project

$ django-admin startproject blog

Running your project

$ python manage.py runserver

System check identified no issues (0 silenced).

You have 15 unapplied migration(s). Your project may not work properly until you apply the migrations for app(s): admin, auth, contenttypes, sessions.
Run 'python manage.py migrate' to apply them.

August 16, 2018 - 09:58:36
Django version 2.1, using settings 'blog.settings'
Starting development server at http://127.0.0.1:8000/
Quit the server with CONTROL-C.

The unapplied migrations refer to the default migration files included when you start a django project.

To synchronize these migration files, simply run migrate

$ python manage.py migrate

Running migrations:
  Applying contenttypes.0001_initial... OK
  Applying auth.0001_initial... OK
  Applying admin.0001_initial... OK
  Applying admin.0002_logentry_remove_auto_add... OK
  Applying admin.0003_logentry_add_action_flag_choices... OK
  Applying contenttypes.0002_remove_content_type_name... OK
  Applying auth.0002_alter_permission_name_max_length... OK
  Applying auth.0003_alter_user_email_max_length... OK
  Applying auth.0004_alter_user_username_opts... OK
  Applying auth.0005_alter_user_last_login_null... OK
  Applying auth.0006_require_contenttypes_0002... OK
  Applying auth.0007_alter_validators_add_error_messages... OK
  Applying auth.0008_alter_user_username_max_length... OK
  Applying auth.0009_alter_user_last_name_max_length... OK
  Applying sessions.0001_initial... OK

The default database in our project is currently set to SQLite named db.sqlite3.

Creating a django project's app

$ cd blog
$ python manage.py startapp posts

The project structure should look like

$ find .
./posts
./posts/migrations
./posts/migrations/__init__.py
./posts/models.py
./posts/__init__.py
./posts/apps.py
./posts/admin.py
./posts/tests.py
./posts/views.py
./db.sqlite3
./blog
./blog/__init__.py
./blog/__pycache__
./blog/__pycache__/settings.cpython-36.pyc
./blog/__pycache__/wsgi.cpython-36.pyc
./blog/__pycache__/__init__.cpython-36.pyc
./blog/__pycache__/urls.cpython-36.pyc
./blog/settings.py
./blog/urls.py
./blog/wsgi.py
./manage.py

2. Model

Each model instance is a definitive source of the information about your data. In general, each model pertains to a single table in your database.

# djangoapi/blog/posts/models.py
from django.db import models

# Create your models here.

class Post(models.Model):
    title = models.CharField(max_length=255)
    content = models.TextField()
    is_featured = models.BooleanField(default=False)

    def __str__(self):
        return self.name

__str__ is called by the str() built-in function and by the print statement to compute the "informal" string representation of an object.
If you try running makemigrations, django won't see those changes yet.

$ No changes detected

To solve this, add your posts app to your project's installed apps.

# djangoapi/blog/blog/settings.py

INSTALLED_APPS = [
    'django.contrib.admin',
    'django.contrib.auth',
    'django.contrib.contenttypes',
    'django.contrib.sessions',
    'django.contrib.messages',
    'django.contrib.staticfiles',
    'posts' # Add it here
]

To continue with the migration of models

$ python manage.py makemigrations

Migrations for 'posts':
  posts/migrations/0001_initial.py
    - Create model Post

$ python manage.py migrate

Operations to perform:
  Apply all migrations: admin, auth, contenttypes, posts, sessions
Running migrations:
  Applying posts.0001_initial... OK


3. Serialization

Serializers allow data structure or object state to be translated into a format that can be stored or transmitted and be reconstructed later on.

Create API's serializers.py and views.py files and isolate them like this

# posts/api
posts/api/serializers.py
posts/api/views.py

# posts/migrations
posts/migrations/

# posts
posts/admin.py
posts/apps.py
posts/models.py
posts/tests.py
posts/views.py
# posts/api/serializers.py

from ..models import Post
from rest_framework import serializers

class PostSerializer(serializers.ModelSerializer):
    class Meta:
        model = Post
        fields = ('title', 'content', 'is_featured') # if not declared, all fields of the model will be shown

In this tutorial we have used ModelSerializer, more on this.

4. Views

A view function, or view for short, is a Python function that takes a Web request and returns a Web response.

# posts/api/views.py

from ..models import Post
from . import serializers
from rest_framework import generics, status
from rest_framework.response import Response

class PostListView(generics.ListAPIView):
    queryset = Post.objects.all()
    serializer_class = serializers.PostSerializer

As seen above, ListAPIView is used for read-only endpoints to represent a collection of model instances.

In this code snippet, we use generics view methods from the rest_framework, more on this.

5. URLs

This is where we setup our routes or URL paths to our designated views in which we expect specific responses for each.

# posts/urls.py

from django.urls import path
from . import views
from .api import views

urlpatterns = [
    path('', views.PostListView.as_view(), name=None)
]

6. Finalizing Setup

Ensure that the rest_framework is added to our project's apps.

# djangoapi/blog/blog/settings.py

INSTALLED_APPS = [
    'django.contrib.admin',
    'django.contrib.auth',
    'django.contrib.contenttypes',
    'django.contrib.sessions',
    'django.contrib.messages',
    'django.contrib.staticfiles',
    'rest_framework', # Add it here
    'posts'
]

7. Django Admin

Since we haven't setup our POST requests yet, we will be populating the database through django's admin panel.

To do that, create a superuser account admin with password 1234password.

$ python manage.py createsuperuser --email [email protected] --username admin

Password:
Password (again):
This password is too common.
Bypass password validation and create user anyway? [y/N]: y
Superuser created successfully.

Register the model in the admin panel.

# posts/admin.py

from django.contrib import admin
from .models import Post

# Register your models here.
admin.site.register(Post)

That's it. Visit the admin panel and update posts model's records. More on this.

8. Testing our API

$ python manage.py runserver
GET /api/v1/posts/
HTTP 200 OK
Allow: GET, HEAD, OPTIONS
Content-Type: application/json
Vary: Accept

[
    {
        "title": "Example Post #1",
        "content": "Lorem ipsum dolor sit amet, consectetur adipiscing elit, sed do eiusmod tempor incididunt ut labore et dolore magna aliqua.",
        "is_featured": false
    },
    {
        "title": "Example Post #2",
        "content": "Lorem ipsum dolor sit amet, consectetur adipiscing elit, sed do eiusmod tempor incididunt ut labore et dolore magna aliqua.",
        "is_featured": true
    }
]

Great. Now it's time for us to update our views and finish the standard CRUD operations.

9. Adding more views

POST is a method used for creating (sometimes updating) a resource in the database.

# posts/api/views.py

from ..models import Post
from . import serializers
from rest_framework import generics, status
from rest_framework.response import Response

class PostCreateView(generics.CreateAPIView):
    queryset = Post.objects.all()
    serializer_class = serializers.PostSerializer

    def create(self, request, *args, **kwargs):
        super(PostCreateView, self).create(request, args, kwargs)
        response = {"status_code": status.HTTP_200_OK,
                    "message": "Successfully created",
                    "result": request.data}
        return Response(response)

Most often, we separate List and Create view classes when we want to expose a list of data set while easily preventing a certain request to POST or create a resource in the database for that specific List view.

Usecase always varies for apps, you are opt to use ListCreateAPIView or even ViewSets for combining the logic for a set of related views.

Optional: Since we want to display the data in a more systematic way, we override create method and map our inline custom response handler.

Adding more views with methods GET, PATCH, DELETE to handle a specific blog post detail.

class PostDetailView(generics.RetrieveUpdateDestroyAPIView):
    queryset = Post.objects.all()
    serializer_class = serializers.PostSerializer

    def retrieve(self, request, *args, **kwargs):
        super(PostDetailView, self).retrieve(request, args, kwargs)
        instance = self.get_object()
        serializer = self.get_serializer(instance)
        data = serializer.data
        response = {"status_code": status.HTTP_200_OK,
                    "message": "Successfully retrieved",
                    "result": data}
        return Response(response)

    def patch(self, request, *args, **kwargs):
        super(PostDetailView, self).patch(request, args, kwargs)
        instance = self.get_object()
        serializer = self.get_serializer(instance)
        data = serializer.data
        response = {"status_code": status.HTTP_200_OK,
                    "message": "Successfully updated",
                    "result": data}
        return Response(response)

    def delete(self, request, *args, **kwargs):
        super(PostDetailView, self).delete(request, args, kwargs)
        response = {"status_code": status.HTTP_200_OK,
                    "message": "Successfully deleted"}
        return Response(response)

10. Updating URLs

# posts/urls.py

from django.urls import path
from . import views
from .api import views

urlpatterns = [
    path('', views.PostListView.as_view(), name=None),
    path('create/', views.PostCreateView.as_view(), name=None),
    path('<int:pk>/', views.PostDetailView.as_view(), name=None)
]

Now you can send requests to your API via Postman, your app or do a GETrequests from your browser, examples:

POST /api/v1/posts/create/
HTTP 200 OK
Allow: POST, OPTIONS
Content-Type: application/json
Vary: Accept

{
    "status_code": 200,
    "message": "Successfully created",
    "result": {
        "csrfmiddlewaretoken": "rnSUN3XOIghnXA0yKghnQgxg0do39xhorYene5ALw3gWGThK5MjG6YjL8VUb7v2h",
        "title": "Creating a resource",
        "content": "Howdy mate!"
    }
}
GET /api/v1/posts/1/
HTTP 200 OK
Allow: GET, PUT, PATCH, DELETE, HEAD, OPTIONS
Content-Type: application/json
Vary: Accept

{
    "status_code": 200,
    "message": "Successfully retrieved",
    "result": {
        "title": "Sample Post",
        "content": "Sample Post Content",
        "is_featured": false
    }
}

That's it. You have successfully managed to develop RESTful APIs with DRF! Cheers!

Source code

Available on GitHub.