
AshuraMajestic
Jul 13, 2024
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.
mkdir AshuraWebBlog
cd AshuraWebBlog
mkdir backend
cd backend
mkdir backend
cd backend
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
venv/scripts/activate
Everytime you need to use your backend you need to activate virtualenv
python -m pip install djangorestframework
Important: Be in your backend folder
django-admin startproject ashurawebblog
Now please follow given steps precisely
We will create an app to handle all api calls
django-admin startapp api
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"",
]
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
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""]
admin.py in our api folder and write following code
from django.contrib import admin
from .models import *
admin.site.register(BlogPost)
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
from rest_framework import serializers
from .models import *
class BlogPostSerializer(serializers.ModelSerializer):
class Meta:
model = BlogPost
fields = (
""id"",
""title"",
""introduction"",
""content"",
""date"",
""minutes"",
""username"",
)
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)
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""))]
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.
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
First open termianl and go to our root folder AshuraWebBlog for me whihc contains the backend folder
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
cd frontend
npm install
use the below command and open the given link by the cmd
npm run dev
for me it is http://localhost:5173/
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
cd frontend
npm install @vitejs/plugin-react
npm install tailwindcss postcss autoprefixer
npx tailwindcss init -p
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'),
],
};
Now go to frontend > src > index.css and add the below line above the file
@tailwind base;
@tailwind components;
@tailwind utilities;
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

We will need two pages
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>
)
}
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;
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;
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
now enter the username and password you set for the superuser
You will see the following page