In this blog-series, I will be sharing my experience building an App with features similar to Twitter, using Django REST.
- There will be a code snippet for each step. You can find the entire code on GitHub too: https://github.com/shilpavijay/TwitterClone
- The approach I have taken is TDD – Test Driven Development. There will be a test case for each functionality, followed by the development of that feature.
Setting up the Django Environment
conda create env --name django_env
conda activate django_env
For Django REST Framework:
pip install djangorestframework
# Add to settings.py:
INSTALLED_APPS = [
...
'rest_framework',
]
Let’s begin the Django Project
#To start a Django Project:
django-admin startproject TwitterClone
#Start the Apps:
python manage.py startapp TUsers
python manage.py startapp Tweets
#Add the two Apps to settings.py
INSTALLED_APPS = [
...
'Tweets',
'TUsers',
]
Writing Test Cases:
- Create a tests folder inside the App as shown below.
- This has to be made into a package by creating a ‘__init__.py’.
- All the files in the package should begin with a test_<>
- We will be writing test cases that initially fail and then coding the functionality, with the final goal of passing the test cases.
- Test cases can be run by: ./manage.py test

test_users.py and test_tweets.py
from django.test import TestCase
from TUsers.models import TUser
class TUserTestCase(TestCase):
def setUp(self):
TUser.objects.create(username="mark_cuban",
password="sharktank",
country="USA")
def test_create(self):
self.assertEqual("USA",
TUser.objects.get(username="mark_cuban").country)
from django.test import TestCase
from Tweets.models import TCtweets
from TUsers.models import TUser
class TweetsTestCase(TestCase):
def setUp(self):
user1 = TUser.objects.create(username="lori",password="sharktank",country="USA")
TCtweets.objects.create(username=user1,tweet_text="Hi there!")
def test_create_tweet(self):
user1 = TUser.objects.get(username='lori')
self.assertEqual("Hi there!",TCtweets.objects.get(username=user1).tweet_text)
Adding the models:
TUser/models.py and Tweets/models.py
from django.db import models
from datetime import datetime
get_cur_time = datetime.now().strftime('%m/%d/%Y %I:%M:%S %p')
class TUser(models.Model):
username = models.CharField(max_length=100,unique=True)
password = models.CharField(max_length=100)
country = models.CharField(max_length=100,null=True)
modified_time = models.CharField(max_length=50,default=get_cur_time)
following = models.ManyToManyField('self',related_name='followers',symmetrical=False,blank=True)
blocked = models.BooleanField(default=False)
token = models.CharField(max_length=10000,null=True)
from django.db import models
from TUsers.models import TUser
from datetime import datetime
get_cur_time = datetime.now().strftime('%m/%d/%Y %I:%M:%S %p')
class TCtweets(models.Model):
username = models.ForeignKey(TUser,on_delete=models.CASCADE)
tweet_text = models.CharField(max_length=100,null=True)
time = models.CharField(max_length=50,default=get_cur_time)
retweet = models.ManyToManyField(TUser,related_name="retweeted_users")
like = models.ManyToManyField(TUser,related_name="liked_users")
reply = models.ManyToManyField("self")
comment = models.CharField(max_length=100,null=True)
Swagger
Let us set up Swagger for API documentation:
pip install django-rest-swagger
#Add to settings.py
INSTALLED_APPS = [
...
'rest_framework_swagger',
]
#Add the following to urls.py
from rest_framework_swagger.views import get_swagger_view
schema_view = get_swagger_view(title='Twitter Clone API')
urlpatterns = [
path('admin/', admin.site.urls),
path('docs/',schema_view),
]
If you are using Django 3.x, (which is my case here) there are a few things to be done in order to make Swagger work:
- Enable CoreAPI Schema: Django Rest Framework 3.x deprecated the CoreAPI based schema generation and introduced the OpenAPI schema generation in its place. Currently to continue to use django-rest-swagger we need to re-enable the CoreAPI schema. To settings.py add:
REST_FRAMEWORK =
{'DEFAULT_SCHEMA_CLASS': 'rest_framework.schemas.coreapi.AutoSchema' }
- Change the swagger index.file: {% load staticfiles %} has been deprecated in django 2.x and removed in 3.x. Modify the same in index.html file of swagger in the location: …/Anaconda\envs\dj\Lib\site-packages\rest_framework_swagger\templates\rest_framework_swagger
...
{% load static %} #Remove {% load staticfiles %}
<!DOCTYPE html>
<html lang="en">
<head>
...
...
And finally, you are done. You should see the Swagger API page.

Test Case for APIs
Too test the login API, first let’s write the test case and then build the code for the same. Here’s a sample:
test_users.py
def test_api_login(self):
client = Client()
response = client.post('/login/',
{'username':'mark_cuban'},format='json')
self.assertEqual(200,response.status_code)
In the next blogpost, we will see how to build the REST APIs.
You can find the project code on GitHub: https://github.com/shilpavijay/TwitterClone
Pingback: Django Custom Middleware – Reverie
Pingback: Building a Twitter Clone with Django REST Framework – III – Reverie
Pingback: Twitter Clone with Django REST Framework – II – Reverie