React.js is a powerful JavaScript library developed by Facebook for building user interfaces. It's known for its declarative approach to building components that manage their own state, making it efficient and easy to develop dynamic web applications. It is commonly used in single-page applications (SPAs) where dynamic content updates are essential, and it's often paired with other libraries and tools for state management (like Redux) and routing (like React Router).
Django is a high-level Python web framework that promotes rapid development and clean, pragmatic design. It follows the "Don't Repeat Yourself" (DRY) principle and emphasizes reusability and pluggability of components. Django is well-suited for building data-driven web applications and is known for its scalability, robustness, and extensive ecosystem of third-party packages (like Django REST Framework for building APIs).
When combined, React.js and Django form a powerful stack for building full-stack web applications. Django serves as the backend, handling data storage, business logic, and API endpoints, while React.js powers the frontend, providing an interactive and responsive user interface. This combination leverages the strengths of both technologies. By leveraging React.js for frontend interactivity and Django for backend robustness, developers can create modern web applications that are efficient, maintainable, and scalable.
Install Python: Ensure Python is installed on your system. You can download it from python.org.
Install Virtualenv (Optional but Recommended)
pip install virtualenv
Create a Virtual Environment: Navigate to your project directory and create a virtual environment
cd your_project_directory
virtualenv venv
Activate the Virtual Environment
source venv/bin/activate
Install Django and Django REST Framework
pip install django
pip install djangorestframework
Create a Django Project
django-admin startproject myblog
Navigate to the Project Directory
cd myblog
Verify the Project Structure
myblog/
├── manage.py
└── myblog/
├── __init__.py
├── asgi.py
├── settings.py
├── urls.py
└── wsgi.py
With Node.js and npm installed, create a new React.js project
npx create-react-app frontend
cd frontend
Start the Django development server
python manage.py runserver
In another terminal, start the React development server
npm start
Models represent the data structure of your application and define how data will be stored in the database.
If the app doesn’t exist yet, create one using the following command
python manage.py startapp blog
Open the models.py file inside the appropriate app (typically named blog or similar)
from django.db import models
from django.utils import timezone
from django.contrib.auth.models import User
from taggit.managers import TaggableManager
from django.urls import reverse
from django.core.exceptions import ValidationError
from ckeditor_uploader.fields import RichTextUploadingField
from django.utils.deconstruct import deconstructible
class Category(models.TextChoices):
SALES = 'sales'
MARKETING = 'marketing'
BUSINESS = 'business'
POLITICS = 'politics'
ART = 'art'
class PublishedManager(models.Manager):
def get_queryset(self):
return super(PublishedManager, self).get_queryset().filter(status='published')
@deconstructible
class ImageSizeValidator:
def __init__(self, max_size_mb=0.5):
self.max_size_mb = max_size_mb
def __call__(self, fieldfile_obj):
filesize = fieldfile_obj.file.size
megabyte_limit = self.max_size_mb
if filesize > megabyte_limit * 1024 * 1024:
raise ValidationError(
f"File size exceeds the maximum limit of {megabyte_limit}MB."
)
class Post(models.Model):
title = models.CharField(max_length=200, help_text="Blog post title")
slug = models.SlugField(max_length=600, unique_for_date='publish')
author = models.ForeignKey(
User, on_delete=models.CASCADE, related_name='blog_post', help_text="Choose author for the post")
category = models.CharField(
max_length=50, choices=Category.choices, default=Category.SALES,
help_text="Category for the post"
)
image = models.ImageField(
upload_to='images/',
null=True,
validators=[ImageSizeValidator(max_size_mb=0.5)],
help_text="Image should be less than 500MB"
)
readTime = models.IntegerField(
null=True, help_text="Read time for the post")
body = RichTextUploadingField(help_text="Your blog post")
featured = models.BooleanField(
default=False, help_text="Check to make the post featured")
publish = models.DateTimeField(default=timezone.now)
created = models.DateTimeField(auto_now_add=True)
updated = models.DateTimeField(auto_now_add=True)
STATUS_CHOICES = (('draft', 'Draft'), ('published', 'Published'))
status = models.CharField(
max_length=20, choices=STATUS_CHOICES, default='draft'
)
objects = models.Manager()
published = PublishedManager()
# tags = TaggableManager()
class Meta:
ordering = ('-publish',)
def save(self, *args, **kwargs):
if self.featured:
try:
temp = Post.objects.get(featured=True)
if self != temp:
temp.featured = False
temp.save()
except Post.DoesNotExist:
pass
super(Post, self).save(*args, **kwargs)
def __str__(self):
return self.title
To manage your blog posts via the Django admin interface, register the Post model in blog/admin.py
from django.contrib import admin
from .models import Post
@admin.register(Post)
class PostAdmin(admin.ModelAdmin):
list_display = ('title', 'author', 'publish', 'status', 'featured', 'category', 'readTime')
list_filter = ('status', 'category', 'publish', 'author', 'featured')
search_fields = ('title', 'body')
prepopulated_fields = {'slug': ('title',)}
raw_id_fields = ('author',)
date_hierarchy = 'publish'
ordering = ('-status', '-publish')
Next, create database migrations for your models and apply the migrations to update your database schema
python manage.py makemigrations
python manage.py migrate
API URLs in your project’s main urls.py file
from django.contrib import admin
from django.urls import path, include, re_path
from django.views.generic import TemplateView
from django.conf import settings
from django.conf.urls.static import static
from rest_framework import routers
from backend import views
urlpatterns = [
path('admin/', admin.site.urls),
path('api/blog/', include('backend.urls')),
]
if settings.DEBUG:
urlpatterns += static(settings.MEDIA_URL,
document_root=settings.MEDIA_ROOT)
urlpatterns += [path('.*', TemplateView.as_view(template_name='index.html'))]
admin.site.site_header = "Welcome Dennis"
admin.site.site_title = "Dennis Mbugua Dashboard"
admin.site.index_title = "Dennis Mbugua Blog Administration"
Your settings.py file should typically be similar to this:
from pathlib import Path
import mimetypes
import os
import sys
import dj_database_url
from django.core.management.utils import get_random_secret_key
BASE_DIR = Path(__file__).resolve().parent.parent
SECRET_KEY = os.getenv("DJANGO_SECRET_KEY", get_random_secret_key())
DEBUG = os.getenv("DEBUG", "False") == "True"
ALLOWED_HOSTS = os.getenv("DJANGO_ALLOWED_HOSTS", "127.0.0.1,localhost").split(",")
DEVELOPMENT_MODE = os.getenv("DEVELOPMENT_MODE", "False") == "True"
INSTALLED_APPS = [
'jazzmin',
'django.contrib.admin',
'django.contrib.auth',
'django.contrib.contenttypes',
'django.contrib.sessions',
'django.contrib.messages',
'django.contrib.staticfiles',
'backend',
'rest_framework',
'corsheaders',
]
MIDDLEWARE = [
'django.middleware.security.SecurityMiddleware',
'whitenoise.middleware.WhiteNoiseMiddleware',
"corsheaders.middleware.CorsMiddleware",
"django.middleware.common.CommonMiddleware",
'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',
]
ROOT_URLCONF = 'blog.urls'
TEMPLATES = [
{
'BACKEND': 'django.template.backends.django.DjangoTemplates',
'DIRS': [],
'APP_DIRS': True,
'OPTIONS': {
'context_processors': [
'django.template.context_processors.debug',
'django.template.context_processors.request',
'django.contrib.auth.context_processors.auth',
'django.contrib.messages.context_processors.messages',
],
},
},
]
WSGI_APPLICATION = 'blog.wsgi.application'
if DEVELOPMENT_MODE is True:
DATABASES = {
"default": {
"ENGINE": "django.db.backends.sqlite3",
"NAME": os.path.join(BASE_DIR, "db.sqlite3"),
}
}
elif len(sys.argv) > 0 and sys.argv[1] != 'collectstatic':
if os.getenv("DATABASE_URL", None) is None:
raise Exception("DATABASE_URL environment variable not defined")
DATABASES = {
"default": dj_database_url.parse(os.environ.get("DATABASE_URL")),
}
STATICFILES_STORAGE = "whitenoise.storage.CompressedStaticFilesStorage"
AUTH_PASSWORD_VALIDATORS = [
{
'NAME': 'django.contrib.auth.password_validation.UserAttributeSimilarityValidator',
},
{
'NAME': 'django.contrib.auth.password_validation.MinimumLengthValidator',
},
{
'NAME': 'django.contrib.auth.password_validation.CommonPasswordValidator',
},
{
'NAME': 'django.contrib.auth.password_validation.NumericPasswordValidator',
},
]
CORS_ORIGIN_WHITELIST = [
'http://localhost:3000',
]
LANGUAGE_CODE = 'en-us'
TIME_ZONE = 'Africa/Nairobi'
USE_I18N = True
USE_TZ = True
AWS_ACCESS_KEY_ID = ''
AWS_SECRET_ACCESS_KEY = ''
AWS_STORAGE_BUCKET_NAME = ''
AWS_S3_ENDPOINT_URL = ''
AWS_S3_OBJECT_PARAMETERS = {
'CacheControl': 'max-age=86400',
}
AWS_LOCATION = ''
STATIC_URL = 'https://%s/%s/' % (AWS_S3_ENDPOINT_URL, AWS_LOCATION)
STATICFILES_STORAGE = 'storages.backends.s3boto3.S3Boto3Storage'
DEFAULT_FILE_STORAGE = 'storages.backends.s3boto3.S3Boto3Storage'
static_root = STATIC_ROOT = os.path.join(BASE_DIR, "static")
os.chmod(static_root, 0o755)
DEFAULT_AUTO_FIELD = 'django.db.models.BigAutoField'
Access API Endpoints
Create serializers to convert Django model instances into JSON format for API responses.
from rest_framework import serializers
from .models import Post
class PostSerializer(serializers.ModelSerializer):
class Meta:
model = Post
fields = '__all__' # or specify individual fields if needed
Create views using Django REST Framework to handle API requests
from django.shortcuts import render, get_object_or_404
from rest_framework.response import Response
from requests import Response
from rest_framework import permissions
from rest_framework.views import APIView
from rest_framework import viewsets
from rest_framework import status
from rest_framework.generics import ListAPIView, RetrieveAPIView
from django.core.mail import send_mail
from django.db.models import Count
from backend.models import Post
from taggit.models import Tag
from .serializers import BlogSerializer
from dataclasses import fields
from rest_framework import serializers
from rest_framework.views import APIView
from django.views.decorators.csrf import csrf_exempt
from django.utils import timezone
from django.db import models
now = timezone.now() # get the current time
class PostListView(ListAPIView):
queryset = Post.published.all()
serializer_class = BlogSerializer
class BlogDetailView(RetrieveAPIView):
queryset = Post.published.all()
serializer_class = BlogSerializer
lookup_field = 'slug'
permission_classes = (permissions.AllowAny, )
class BlogFeaturedView(ListAPIView):
queryset = Post.objects.all().filter(featured=True)
serializer_class = BlogSerializer
lookup_field = 'slug'
permission_classes = (permissions.AllowAny, )
class BlogCategoryView(APIView):
serializer_class = BlogSerializer
permission_classes = (permissions.AllowAny, )
http_method_names = ['get', 'head']
def post(self, request, format=None):
self.http_method_names.append("GET")
data = self.request.data
category = data['id']
queryset = Post.objects.order_by(
'-date_created').filter(category__iexact=category)
serializer = BlogSerializer(queryset, many=True)
return Response(serializer.data)
Create URLs for your API endpoints
from django.urls import path, include
from . import views
from .views import PostListView, BlogCategoryView, BlogDetailView, BlogFeaturedView
from .feeds import LatestPostsFeed
app_name = 'blog'
urlpatterns = [
path('', PostListView.as_view(), name='list_view'),
path('category', BlogCategoryView.as_view(), name='category'),
path('featured', BlogFeaturedView.as_view(), name='featured'),
path('<slug>', BlogDetailView.as_view(), name='blog_details'),
path('feed/', LatestPostsFeed(), name='post_feed'),
]
DRF provides powerful tools for building APIs, including serializers, views, and URL routing.
Ensure you have Node.js and npm (Node Package Manager) installed on your system.
Navigate to the directory where you want to create your React.js project, then run the following command to create a new project named my-react-blog (replace my-react-blog with your preferred project name), navigate into the newly created project directory and launch the development server.
npx create-react-app my-react-blog
cd my-react-blog
npm start
Once the React project is set up, you’ll see a directory structure similar to this:
my-react-blog/
├── README.md
├── node_modules/
├── package.json
├── public/
│ ├── index.html
│ └── favicon.ico
└── src/
├── App.css
├── App.js
├── App.test.js
├── index.css
├── index.js
├── logo.svg
└── serviceWorker.js
Integrating Axios for API Requests
npm install axios
Create a directory named components inside the src directory of your React project
cd my-react-blog/src
mkdir components
Inside the components directory, create individual files for each component. Create a component to display a single blog post.
Inside the components directory, create individual files for each component. Create a component to display a single blog post.
import React, { useState, useEffect, useRef } from "react";
import { Helmet } from "react-helmet";
import { Link, useParams } from "react-router-dom";
import Me from "./me.jpeg";
import { BulletList } from "react-content-loader";
import { ToastContainer, toast } from "react-toastify";
import "react-toastify/dist/ReactToastify.css";
import { useReactToPrint } from "react-to-print";
import {
TelegramShareButton,
TelegramIcon,
TwitterShareButton,
TwitterIcon,
EmailShareButton,
EmailIcon,
WhatsappIcon,
WhatsappShareButton,
} from "react-share";
import BlogAPI from "../../API/BlogAPI";
import RecentArticles from "./recentArticles";
import NotFound from "../notFound/NotFound";
export default function BlogDetails() {
// SCROLL TO TOP
const scrollToTop = () => {
window.scrollTo(0, 0);
};
const MyBulletListLoader = () => <BulletList />;
const [error, setError] = useState(false);
const [blog, setBlog] = useState({});
const { slug } = useParams();
const [featuredBlog, setFeaturedBlog] = useState([]);
const [loading, setLoading] = useState(true);
const copied = () => toast("👏 Copied to Clipboard!");
const print = () => toast("Send to print!");
const [open, setOpen] = useState(false);
const handleCopyClipBoard = () => {
setOpen(true);
navigator.clipboard.writeText(window.location.toString());
};
const componentRef = useRef();
const handlePrint = useReactToPrint({
content: () => componentRef.current,
});
useEffect(() => {
// Loader
setLoading(true);
setTimeout(() => {
setLoading(false);
}, 1000);
// FeaturedAticle
const fetchData = async () => {
try {
const res = await BlogAPI.get(`/api/blog/featured`);
// If there are no featured posts
if (res.data && res.data.length > 0) {
setFeaturedBlog(res.data[0]);
}
} catch (err) {}
};
fetchData();
// BlogPost
const fetchBlog = async () => {
try {
const response = await BlogAPI.get(`/api/blog/${slug}`); // <-- passed to API URL
setBlog(response.data);
} catch (err) {
if (err.response && err.response.status === 404) {
setError(true);
} else {
// Handle other errors, such as network issues
// console.error(err);
}
}
};
fetchBlog();
}, [slug]);
const createBlog = () => {
return { __html: blog.body };
};
const capitalLetter = (word) => {
if (word) return word.charAt(0).toUpperCase() + word.slice(1);
return "";
};
const shareUrl = `https://www.yourwebsite.com/${slug}`;
let getTime = (blog) => {
const options = { year: "numeric", month: "long", day: "numeric" };
return new Date(blog).toLocaleDateString("en", options);
};
return (
<>
{error ? (
<NotFound />
) : (
<div className="container mt-5">
<div className="row">
<div className="col-lg-8 mt-5 mb-5">
<nav aria-label="breadcrumb">
<ol className="breadcrumb bg-white">
<li className="breadcrumb-item fw-bold">
<Link to="/articles">
<i className="fa fa-angle-double-left" /> Back to blog
</Link>
</li>
</ol>
</nav>
{loading ? (
<MyBulletListLoader />
) : (
<article>
<section
ref={componentRef}
removeAfterPrint={true}
documentTitle="www.dennismbugua.co.ke"
>
<header className="mb-4">
<h1 className="fw-bolder mb-1">
{capitalLetter(blog.title)}
</h1>
</header>
<p className="post-meta">
<i className="fa fa-calendar-days"></i>{" "}
{getTime(blog.updated)}
</p>
<figure className="mb-4">
<img
className="img-fluid rounded w-100"
src={blog.image}
alt={blog.title}
style={{
height: "600px",
width: "500px",
borderRadius: "10px",
}}
/>
</figure>
<p
className="fs-5 text-dark"
dangerouslySetInnerHTML={createBlog()}
/>
</section>
<section className="text-center border-top border-bottom py-4 mb-4">
<p>
<strong>
Share this post with your friends and spread the
knowledge!
</strong>
</p>
<ul className="mr-3">
<li>
<TwitterShareButton
url={shareUrl}
title={blog.title}
via={"dennismbugua_"}
>
<TwitterIcon size={40} round={true} />
</TwitterShareButton>
</li>
<li>
<EmailShareButton
subject="IMPORTANT AND URGENT!"
url={shareUrl}
body="This is one of the most awesome article I've read today"
>
<EmailIcon size={40} round={true} />
</EmailShareButton>
</li>
<li>
<WhatsappShareButton
url={shareUrl}
title={blog.title}
separator={" "}
>
<WhatsappIcon size={40} round={true} />
</WhatsappShareButton>
</li>
<li>
<TelegramShareButton url={shareUrl} title={blog.title}>
<TelegramIcon size={40} round={true} />
</TelegramShareButton>
</li>
<li>
<i
className="fa wp-icon fa-solid fa-print fa-1x cursor-pointer"
onClick={() => {
handlePrint();
print();
}}
></i>
</li>
<li>
<i
className="wp-icon fa fa-copy fa-solid fa-1x"
onClick={() => {
handleCopyClipBoard();
copied();
}}
></i>
</li>
<ToastContainer />
</ul>
</section>
</article>
)}
</div>
<div className="col-lg-4">
<div className="position-sticky" style={{ top: "6rem" }}>
{/* FeaturedPost */}
<div className="card">
<div
style={{
borderRadius: "10px",
padding: "10px",
border: "2px",
}}
>
<div className="card-header text-uppercase fw-bold text-center">
Featured Article
</div>
<div className="card-body" style={{ borderRadius: "10px" }}>
<p>
{loading ? (
<MyBulletListLoader />
) : featuredBlog.length === 0 ? (
<p>Stay tuned for my upcoming featured articles!</p>
) : (
<Link
to={`/articles/${featuredBlog.slug}`}
onClick={scrollToTop}
className="text-decoration-none fw-bold fs-5"
>
{capitalLetter(featuredBlog.title)}
</Link>
)}
</p>
<hr className="text-dark" />
</div>
</div>
</div>
{/* Recent Articles */}
<div className="card mt-5">
<div className="card-header text-uppercase fw-bold text-center">
Recent Article
</div>
<RecentArticles />
</div>
</div>
</div>
</div>
</div>
)}
</>
);
}
Create a component to display a list of blog posts
import React, { useEffect, useState } from "react";
import { Link } from "react-router-dom";
import { BulletList } from "react-content-loader";
import BlogAPI from "../../API/BlogAPI";
export default function BlogFeeds() {
// SCROLL TO TOP
const scrollToTop = () => {
window.scrollTo(0, 0);
};
const MyBulletListLoader = () => <BulletList />;
const [blogs, setBlogs] = useState([]);
const [filter, setFilter] = useState("");
const [loading, setLoading] = useState(true);
const searchText = (event) => {
setFilter(event.target.value);
};
const dataSearch = blogs.filter((blogPost) => {
return Object.keys(blogPost).some((key) =>
blogPost[key]
.toString()
.toLowerCase()
.includes(filter.toString().toLowerCase())
);
});
const capitalLetter = (word) => {
return word ? `${word.charAt(0).toUpperCase()}${word.slice(1)}` : "";
};
useEffect(() => {
// Loader
setLoading(true);
setTimeout(() => {
setLoading(false);
}, 2500);
const fetchBlogs = async () => {
try {
const res = await BlogAPI.get(`/api/blog`);
setBlogs(res.data);
} catch (err) {
// Handle error
}
};
fetchBlogs();
}, []);
const getBlogs = () => {
return dataSearch.map((blogPost, i) => (
<React.Fragment key={i}>
<div className="col">
<div className="post-preview border-bottom">
{loading ? (
<MyBulletListLoader />
) : (
<Link
to={`/articles/${blogPost.slug}`}
onClick={scrollToTop}
className="text-decoration-none"
>
<h3 className="post-title">{capitalLetter(blogPost.title)}</h3>
<h4 className="post-subtitle">
{capitalLetter(blogPost.subtitle)}
</h4>
<p>
<i className="fa-solid fa-clock"></i> {blogPost.readTime} Min
Read
</p>
</Link>
)}
</div>
</div>
</React.Fragment>
));
};
return (
<>
<div className="container" style={{ marginTop: "100px" }}>
<div className="row height d-flex justify-content-center align-items-center">
<div className="col-md-8">
<div className="search">
<i className="fa fa-search"></i>
<input
type="text"
className="form-control"
value={filter}
onChange={searchText.bind(this)}
placeholder="Search an article"
/>
</div>
</div>
</div>
</div>
<div className="container px-4 px-lg-5 mb-5">
<div className="row gx-4 gx-lg-5 justify-content-center">
<div className="col-md-10 col-lg-8 col-xl-9 ">{getBlogs()}</div>
</div>
</div>
</>
);
}
Create a component to display latest blog posts
import React, { useEffect, useState } from "react";
import { Link } from "react-router-dom";
import { BulletList } from "react-content-loader";
import BlogAPI from "../../API/BlogAPI";
export default function RecentArticles() {
// SCROLL TO TOP
const scrollToTop = () => {
window.scrollTo(0, 0);
};
const MyBulletListLoader = () => <BulletList />;
const [blogs, setBlogs] = useState([]);
const [loading, setLoading] = useState(true);
const capitalLetter = (word) => {
return word ? `${word.charAt(0).toUpperCase()}${word.slice(1)}` : "";
};
useEffect(() => {
// Loader
setLoading(true);
setTimeout(() => {
setLoading(false);
}, 2000);
const fetchBlogs = async () => {
try {
const res = await BlogAPI.get(`/api/blog`);
setBlogs(res.data);
} catch (err) {
// Handle error
}
};
fetchBlogs();
}, []);
const getBlogs = () => {
return blogs.slice(0, 2).map((blogPost, index) => (
<div className="card-body" key={index} style={{ borderRadius: "10px" }}>
{loading ? (
<MyBulletListLoader />
) : (
<Link
to={`/articles/${blogPost.slug}`}
onClick={scrollToTop}
className="text-decoration-none fw-bold fs-5"
>
{capitalLetter(blogPost.title)}
</Link>
)}
<hr className="text-dark" />
</div>
));
};
return <div>{getBlogs()}</div>;
}
Create a component to display featured blog posts
import React, { useState, useEffect } from "react";
import { Link, useParams } from "react-router-dom";
import { BulletList } from "react-content-loader";
import BlogAPI from "../../API/BlogAPI";
export default function FeaturedArticles() {
const scrollToTop = () => {
window.scrollTo(0, 0);
};
const MyBulletListLoader = () => <BulletList />;
const { slug } = useParams();
const [featuredBlog, setFeaturedBlog] = useState([]);
const [loading, setLoading] = useState(true);
useEffect(() => {
setLoading(true);
const fetchData = async () => {
try {
const res = await BlogAPI.get("/api/blog/featured");
if (res.data && res.data.length > 0) {
setFeaturedBlog(res.data[0]);
}
setLoading(false);
} catch (err) {
console.log(err);
setFeaturedBlog([]);
setLoading(false);
}
};
fetchData();
}, []);
return (
<>
<div className="bg-image p-5 text-center shadow-1-strong rounded mb-5 text-white">
{loading ? (
<h1 className="mb-3 h2">
<MyBulletListLoader />
</h1>
) : featuredBlog.length === 0 ? (
<h1 className="mb-3 h2">Stay tuned for my upcoming featured articles!</h1>
) : (
<>
<h1 className="mb-3 h2">
<Link to={`/articles/${featuredBlog.slug}`} onClick={scrollToTop} className="text-decoration-underline text-white fw-bold text-capitalize display-3">
{featuredBlog.title}
</Link>
</h1>
<button type="button" className="btn btn-primary">
<h6 className="fw-bold">
<Link to={`/articles/${featuredBlog.slug}`} className="text-white fs-3">
Explore Now
</Link>
</h6>
</button>
</>
)}
</div>
</>
);
}
Use these components in your App.js or any other parent component to render blog-related content
import React from "react";
import { Routes, Route, useNavigate } from "react-router-dom";
import BlogFeeds from "./components/blog/BlogFeeds";
import { lazy, Suspense } from "react";
import { ErrorBoundary } from "react-error-boundary";
import Home from "./components/homePage/Home";
import ErrorFallback from "./components/error/ErrorFallback";
const BlogDetails = lazy(() => import("./components/blog/BlogDetails"));
function App() {
const navigate = useNavigate();
return (
<>
{/* <NavBar /> */}
<Routes>
<Route
exact
path="/articles/:slug"
element={
<ErrorBoundary
onReset={() => navigate("/")}
fallbackRender={({ error, resetErrorBoundary }) => (
<ErrorFallback
error={error}
resetErrorBoundary={resetErrorBoundary}
/>
)}
>
<Suspense>
<>
<BlogDetails />
</>
</Suspense>
</ErrorBoundary>
}
/>
<Route
exact
path="/articles"
element={
<ErrorBoundary
onReset={() => navigate("/")}
fallbackRender={({ error, resetErrorBoundary }) => (
<ErrorFallback
error={error}
resetErrorBoundary={resetErrorBoundary}
/>
)}
>
<Suspense>
<BlogFeeds />
</Suspense>
</ErrorBoundary>
}
/>
<Route
exact
path="/"
element={
<ErrorBoundary
onReset={() => navigate("/")}
fallbackRender={({ error, resetErrorBoundary }) => (
<ErrorFallback
error={error}
resetErrorBoundary={resetErrorBoundary}
/>
)}
>
<Suspense>
<>
<Home />
</>
</Suspense>
</ErrorBoundary>
}
/>
</Routes>
</>
);
}
export default App;
Get your site in a git repository and then push that repository to GitHub. Initialize your Django project as a git repository
git init
Exclude certain files added that are unnecessary for deployment by adding that directory to Git’s ignore list
nano .gitignore
Add files to your repositories
git add .
Make your initial commit
git commit -m "Initial Blog App"
Push your local files to GitHub
git remote add origin https://github.com/your_username/django-app
Rename the default branch main, to match what GitHub expect
git branch -M main
Push your main branch to GitHub’s main branch
git push -u origin main
Your files will transfer. Enter your GitHub credentials when prompted to push your code.
[secondary_label Output]
Enumerating objects: 12, done.
Counting objects: 100% (12/12), done.
Delta compression using up to 8 threads
Compressing objects: 100% (9/9), done.
Writing objects: 100% (12/12), 3.98 KiB | 150.00 KiB/s, done.
Total 12 (delta 1), reused 0 (delta 0)
remote: Resolving deltas: 100% (1/1), done.
To github.com:yourUsername/django-app.git
* [new branch] main -> main
Branch 'main' set up to track remote branch 'main' from 'origin'.
python manage.py migrate
python manage.py createsuperuser
Hurray! And now you have a Django app deployed to App Platform. Any changes that you make and push to GitHub will be automatically deployed.
Involves preparing your project for production, building optimized assets, and deploying those assets to a web server or a cloud platform.
There are several options for hosting including Netlify, Vercel, AWS S3, GitHub Pages, Firebase Hosting, or Surge.sh are ideal for hosting static websites. You can also deploy frontend alongside backend on platforms like Digital Ocean, AWS Elastic Beanstalk, Google Cloud Platform, or Azure App Service.
Get a custom domain, configure DNS settings to point to your hosting provider
Integrate email newsletter functionality using ReactJS with ConvertKit (popular for content creators) or even Django’s email capabilities or third-party services like Mailchimp or SendGrid to enable users to subscribe and receive updates.
Implement user authentication and authorization using Django’s built-in authentication system or third-party libraries like Django Allauth or OAuth providers.
Add real-time features using WebSockets with Django Channels or integrate with third-party services like Pusher or Firebase for live updates and messaging.
Utilize libraries like Chart.js or D3.js for interactive data visualization, presenting insights and trends from your blog content.
Set up automated testing using Django’s test framework and frontend testing with tools like Jest or Cypress. Implement continuous integration and deployment (CI/CD) pipelines with GitHub Actions or GitLab CI.
Enable PWA features like offline support, push notifications, and background sync using service workers to enhance the user experience.
Support multiple languages and locales using Django’s internationalization features and react-i18next for the frontend, making your blog accessible to a global audience.
Integrate analytics tools like Google Analytics or Matomo for tracking user behavior and engagement. Set up application performance monitoring (APM) with tools like New Relic or Datadog to ensure optimal performance.
Implement additional security measures such as HTTPS, Content Security Policy (CSP), and cross-site scripting (XSS) protection to safeguard your blog from security threats and vulnerabilities.
Happy Coding!
Meet Dennis, a seasoned software engineer with 10 years of experience transforming ideas into digital reality. He has successfully guided countless projects from concept to deployment, bringing innovative solutions to life. With a passion for crafting exceptional software, Dennis has helped countless clients achieve their goals.
Click here to learn more
No popular posts available.
No related posts found.