Ashura Blogs LogoAshura
Blogs

Setting Up Django Backend and React Frontend with Tailwind CSS

profile

AshuraMajestic

Jul 13, 2024

book

20 min

This guide will walk you through the process of setting up a Django backend and a React frontend using Tailwind CSS. Follow the steps carefully to ensure everything is set up correctly.

Prerequisites

  1. Python installed on your system.
  2. Node.js installed on your system.
  3. Visual Studio Code (VS Code) installed for code editing.

Steps we going to follow:

  1. Setting up our Django Backend
  2. Creating our ReactJs Frontend(Going to Use Vite+ReactJs as it is faster)
  3. Integrating Tailwindcss

Setting Up Our Django Backend

Step 1: First we need to create our main root folder, as i am Using AshuraWebBlog you can use any name

mkdir AshuraWebBlog
cd AshuraWebBlog

Step 2: Create a Backend Folder

mkdir backend
cd backend

Step 3: Create a Backend Folder

mkdir backend
cd backend

Step 4: Creating virtual environment (optional)

I am going to create a virutal env so it will be isolated from my global environment

python -m pip install virtualenv

After the download is completed We will make the virtual environment

python -m virtualenv venv

step 5: Start the virtual env

venv/scripts/activate

Everytime you need to use your backend you need to activate virtualenv

step 6: Installing packages needed for Backend

python -m pip install djangorestframework

step 7 : Create django backend

Important: Be in your backend folder

django-admin startproject ashurawebblog

Now please follow given steps precisely

  1. rename ashurawebblog in backend to ashurawebblog2
  2. now move the ashurawebblog( which is in the renamed ashurawebblog) and manage.py to backend folder
  3. now delete the ashurawebblog2

step 8 : Create new app

We will create an app to handle all api calls

django-admin startapp api

step 9: Make chnagesd in the settings

Go to the settings.py in the backend > ashurawebblog and edit the following lines

INSTALLED_APPS = [
    ""django.contrib.admin"",
    ""django.contrib.auth"",
    ""django.contrib.contenttypes"",
    ""django.contrib.sessions"",
    ""django.contrib.messages"",
    ""django.contrib.staticfiles"",
    ""rest_framework"",
    ""api"",
]

step 10 : setting up the api

  1. create urls.py inside the api folder

    from django.urls import path
    from .views import *
    from rest_framework.routers import DefaultRouter
    
    router = DefaultRouter()
    router.register(""blogpost"", BlogPostViewSet, basename=""blogpost"")
    urlpatterns = router.urls
    
    
  2. Install cors

    pip install django-cors-headers
    

    and the cors.headers to our installed apps in settings.py

    Go to the settings.py in the `backend > ashurawebblog ` and edit the following lines
    
INSTALLED_APPS = [
    INSTALLED_APPS = [
    ""django.contrib.admin"",
    ""django.contrib.auth"",
    ""django.contrib.contenttypes"",
    ""django.contrib.sessions"",
    ""django.contrib.messages"",
    ""django.contrib.staticfiles"",
    ""rest_framework"",
    ""api"",
#add this line here
    ""corsheaders"",
]
MIDDLEWARE = [
#add this line at the top
    ""corsheaders.middleware.CorsMiddleware"",
    ""django.middleware.security.SecurityMiddleware"",
    ""django.contrib.sessions.middleware.SessionMiddleware"",
    ""django.middleware.common.CommonMiddleware"",
    ""django.middleware.csrf.CsrfViewMiddleware"",
    ""django.contrib.auth.middleware.AuthenticationMiddleware"",
    ""django.contrib.messages.middleware.MessageMiddleware"",
    ""django.middleware.clickjacking.XFrameOptionsMiddleware"",
]

CORS_ALLOWED_ORIGINS = [""http://localhost:3000""]
  1. Edit admin.py Goto admin.py in our api folder and write following code
    from django.contrib import admin
    from .models import *
    
    admin.site.register(BlogPost)
    
    
  2. Edit models.py or add our blogpost model
from django.db import models


class BlogPost(models.Model):
    title = models.CharField(max_length=60)
    content = models.TextField()
    introduction = models.CharField(max_length=300)
    date = models.DateField(auto_now_add=True)
    minutes = models.IntegerField()
    username = models.CharField(max_length=50)

    def __str__(self):
        return self.title

  1. Add serializers.py
    from rest_framework import serializers
    from .models import *
    
    
    class BlogPostSerializer(serializers.ModelSerializer):
        class Meta:
            model = BlogPost
            fields = (
                ""id"",
                ""title"",
                ""introduction"",
                ""content"",
                ""date"",
                ""minutes"",
                ""username"",
            )
    
    
  2. lastly edit the views.py
    from django.shortcuts import render
    from django.http import HttpResponse
    from rest_framework import viewsets, permissions
    from .serializers import *
    from rest_framework.response import Response
    from .models import *
    
    
    class BlogPostViewSet(viewsets.ViewSet):
        permission_classes = [permissions.AllowAny]
        queryset = BlogPost.objects.all()
        serializer_class = BlogPostSerializer
    
        def list(self, request):
            queryset = self.queryset
            serializer = self.serializer_class(queryset, many=True)
            return Response(serializer.data)
    
        def create(self, request):
            serializer = self.serializer_class(data=request.data)
            if serializer.is_valid():
                serializer.save()
                return Response(serializer.data)
            else:
                return Response(serializer.errors, status=400)
    
        def retrieve(self, request, pk=None):
            blogpost = self.queryset.get(pk=pk)
            serializer = self.serializer_class(blogpost)
            return Response(serializer.data)
    
        def update(self, request, pk=None):
            blogpost = self.queryset.get(pk=pk)
            serializer = self.serializer_class(blogpost, data=request.data)
            if serializer.is_valid():
                serializer.save()
                return Response(serializer.data)
            else:
                return Response(serializer.errors, status=400)
    
        def destroy(self, request, pk=None):
            blogpost = self.queryset.get(pk=pk)
            blogpost.delete()
            return Response(status=204)
    
    

step11: Edit urls.py

Now go to urls.py in the backend > ashurawebblog and edit it

from django.contrib import admin
from django.urls import path, include

urlpatterns = [path(""admin/"", admin.site.urls), path("""", include(""api.urls""))]

step 12: create superuser

To be able to log into the admin application, we need to create a user.

This is done by typing this command in the command view:

python manage.py createsuperuser

Which will give this prompt:

Username:

Here you must enter: username, e-mail address, (you can just pick a fake e-mail address), and password:

Username: johndoe
Email address: johndoe@dummymail.com
Password:
Password (again):
This password is too short. It must contain at least 8 characters.
This password is too common.
This password is entirely numeric.
Bypass password validation and create user anyway? [y/N]:

My password did not meet the criteria, but this is a test environment, and I choose to create user anyway, by enter y:

Bypass password validation and create user anyway? [y/N]: y

If you press [Enter], you should have successfully created a user:

Superuser created successfully.

step 13: Finishing up backend

now open terminal and run following commands in backend folder

python manage.py makemigrations
python manage.py migrate

Now our backend is ready you can start it and see it

python manage.py runserver

Creating our ReactJs Frontend(Going to Use Vite+ReactJs as it is faster)

First open termianl and go to our root folder AshuraWebBlog for me whihc contains the backend folder

step 1: Intialize vite in our project

npm create vite@latest

It will ask some question like projectname and other, answer just like given below


> npx
> create-vite

√ Project name: ... frontend
√ Select a framework: » React
√ Select a variant: » JavaScript +  SWC

Scaffolding project in AshuraWebBlog\frontend...

Done. Now run:

  cd frontend
  npm install
  npm run dev

step 2: Install modules

cd frontend
npm install

step 3: Run the server to check if it is running or not

use the below command and open the given link by the cmd

npm run dev

for me it is http://localhost:5173/

step 4: edit the homepage

Go to frontend > src > App.jsx and edit it

import { useState } from 'react'
import './App.css'

function App() {

  return (
    <div className='hello text-3xl'>
      Hello world
    </div>
  )
}

export default App

Now our frontend is half ready we need to also install tailwind for the desinging

Integrating the tailwindcss

step 1: Install the tailwind module

cd frontend
npm install @vitejs/plugin-react
npm install tailwindcss postcss autoprefixer
npx tailwindcss init -p

step 2: Edit files

got tailwind.config.js nad edit it

/** @type {import('tailwindcss').Config} */
module.exports = {
  content: [
    "./src/**/*.{js,jsx,ts,tsx}",
  ],
  theme: {
    extend: {},
  },
  plugins: [],
}

Edit vit.config.js


import { defineConfig } from "vite";
import react from "@vitejs/plugin-react";
import tailwindcss from ""tailwindcss"";

// https://vitejs.dev/config/
export default defineConfig({
  plugins: [react()],
  css: {
    postcss: {
      plugins: [tailwindcss()],
    },
  },
  server: {
    port: 3000
  }
});

Edit postcss.config,js

module.exports = {
  plugins: [
    require('tailwindcss'),
    require('autoprefixer'),
  ],
};

step 3 : now connecting it with the frontend

Now go to frontend > src > index.css and add the below line above the file

@tailwind base;
@tailwind components;
@tailwind utilities;

step 4: Now start the fronend server and you will see that now you can use the tailwind

You can also edit he App.jsx file and see that the page is working or not

import { useState } from 'react'
import './App.css'

function App() {

  return (
    <div className='hello text-6xl text-[#345432] font-bold'>
      Hello world
    </div>
  )
}

export default App

output Tailwindcss Output

Desinging and Coding our frontend

We will need two pages

  1. Home Page where we will show all the Blogs
  2. Blog page: When user click on the blogs on home page the user can see the full blog on this page
  3. Axios : Where we will intilaize the Fetch function to use on all pages

step 1: Creating componenets

Go to frontend > src and create component folder and add three Components

cd frontend
cd src
mkdir component
type nul > Home.jsx
type nul > Blog.jsx
type nul > Axios.jsx

and intialize all the Components

Home.jsx

import React from 'react'

export default function Home() {
  return (
    <div>Home</div>
  )
}

Blog.jsx

import React from 'react'

export default function Blog() {
  return (
    <div>blog</div>
  )
}

step 2: Now create the Axios.jsx Instance

we will use axios.jsx as the instance which will work as api between the backend and frontend

import axios from 'axios';
const baseUrl = 'https://127.0.0.1:8000/';
const AxiosInstance = axios.create({
    baseURL: baseUrl,
    timeout: 10000,
    headers: {
        'Content-Type': 'application/json',
        accept: ""application/json""
    }
})
export default AxiosInstance;

step 3: Now add all the Components in the App.jsx

We will use router for routing

import React from 'react';
import { BrowserRouter, Route, Routes } from 'react-router-dom'
import './App.css';
import Home from './components/Home';
import BlogDetail from './components/Blog';
function App() {
  return (
    <div className='App'>
      <BrowserRouter>
        <Routes>
          <Route path='/' element={<Home />} />
          <Route path='/blog/:id' element={<Blog />} />
        </Routes>
      </BrowserRouter>
    </div>
  );
}

export default App;

step 4: Coding

Now lets start the desinging process and coding i will write the code dirrectly as i dont have to teach you about html and what is recat and how it works. We will just use the Axios to fecth the data from the backedn and taiwlind to design the page our Home.jsx will look lioke this after everything

import React, { useEffect, useState } from 'react';
import AxiosInstance from '../components/Axios';
// import IMG from '../assets/pp.png'
import { Link } from 'react-router-dom';


export default function Home() {

    const [myData, setMyData] = useState({});
    const getData = () => {
        AxiosInstance.get(`blogpost/`).then((res) => {
            const reversedData = res.data.reverse();
            setMyData(reversedData);
        }).catch((error) => {
            console.error(""There was an error fetching the data!"", error);
        });
    };

    useEffect(() => {
        getData();
    }, []);


    return (
        <div className='container mx-auto home-style mt-24'>
            <div className='grid grid-cols-3 gap-x-4'>
                <div className='col-span-2'>
                    <h1 className='uppercase font-bold text-4xl my-8 text-white heading'>CODING ARTICLES</h1>
                    <div className='blogs grid'>
                        {myData.length > 0 ? (
                            myData.map((post) => (
                                <div key={post.id} className='blog grid row w-100 my-5 px-8 bg-[#BF3D6B] rounded-xl'>
                                    <div className='row my-4 text-white font-bold text-3xl'>
                                        <h1>{post.title}</h1>
                                    </div>
                                    <div className='row flex flex-row items-center '>
                                        {/* <img src={IMG} alt='profile' className='w-9 pp' /> */}
                                        <p className='ml-2 text-white'>{post.username}</p>
                                        <p className='ml-5 text-white'>{new Date(post.date).toLocaleDateString()}</p>
                                    </div>
                                    <div className='row my-3 text-white text-xl'>
                                        <p>{post.introduction}</p>
                                    </div>
                                    <div className='row my-5'>
                                        <Link to={`/blog/${post.id}`}>
                                            <button className='px-2 py-2 bg-[#E09129] rounded-md text-white font-semibold'>
                                                Read More
                                            </button>
                                        </Link>
                                    </div>
                                </div>
                            ))
                        ) : (
                            <p className='text-white'>No blog posts available.</p>
                        )}
                    </div>
                </div>
                <div className=""col-span-1""></div>
            </div>
        </div>
    )
}

You can desing it yourself using the tailwind.css but am going to use this design

Now our tailwind is ready to show alol the blogs but wer also need to design the Blog.jsx

import React, { useEffect, useState } from 'react';
import { useParams } from 'react-router-dom';
import AxiosInstance from '../components/Axios';

export default function BlogDetail() {
    const { id } = useParams();
    const [blog, setBlog] = useState(null);
    console.log(blog);
    useEffect(() => {
        AxiosInstance.get(`blogpost/${id}/`)
            .then((res) => {
                setBlog(res.data);
            })
            .catch((err) => {
                console.error(""Error fetching data: "", err);
            });
    }, [id]);

    if (!blog) {
        return <div>Loading...</div>;
    }

    return (

        <div className='container mx-auto my-20 px-10 blog-style'>
            <div className=""flex"">
                <div className=""w-1/12"">
                </div>

                {/* Middle Column */}
                <div className=""w-10/12 bg-[#BF3D6B] p-6 rounded-lg mx-4"">
                    <div className=""grid gap-4"">
                        <div className=""row"">
                            <h1 className=""text-white text-center text-4xl font-bold mt-4 mb-3"">{blog.title}</h1>
                        </div>
                        <div className=""row flex space-x-4"">
                            <div className='w-4/12 flex flex-row items-center justify-center'>
                                <p className=""text-white ms-2 text-base"">{blog.username}</p>
                            </div>
                            <div className='w-4/12  flex flex-row items-center justify-center'>
                                <p className=""text-white text-base"">{new Date(blog.date).toLocaleDateString('en-US', {
                                    month: 'short',
                                    day: 'numeric',
                                    year: 'numeric'
                                })}</p>
                            </div>
                            <div className='w-4/12  flex flex-row items-center justify-center'>
                                <p className=""text-white ms-4 text-base"">{blog.minutes} min</p>
                            </div>
                        </div>
                        <div className='line'></div>
                        <div className=""row my-3 text-white text-xl mt-5"">
                            <p>{blog.introduction}</p>
                        </div>
                        <div className=""row my-3 text-white prose lg:prose-xl max-w-none"">
                                {blog.content}
                        </div>
                    </div>
                </div>


                <div className=""w-1/12 "">
                </div>
            </div>
        </div>

    );
}

Now everthing is ready Now we can use our site to fullest

But one thing is missing and it is the data itself

Adding the data

Go to your backend folder nad run the python server

Go to http://127.0.0.1:8000/admin/

now enter the username and password you set for the superuser

You will see the following page

Go to blog post and add the data and you can see the data on the frontend after you will turn on both server front end and backend