Introduction
This tutorial will guide you through building a full-featured Django Blogging Application from scratch. The blog will include post creation, editing, deletion, TinyMCE integration for rich text, user authentication, and a beautiful Bootstrap-based frontend.
Project Setup
mkdir django_blog
cd django_blog
python -m venv venv
source venv/bin/activate # On Windows use `venv\Scripts\activate`
pip install django
Now, create a new Django project:
django-admin startproject blog_project .
Creating the Blog App
Run the following command to create a Django app:
python manage.py startapp blog
Installing Required Packages
pip install django-tinymce
Add blog
and tinymce
to INSTALLED_APPS
in settings.py
:
INSTALLED_APPS = [
'django.contrib.admin',
'django.contrib.auth',
'django.contrib.contenttypes',
'django.contrib.sessions',
'django.contrib.messages',
'django.contrib.staticfiles',
'blog',
'tinymce',
]
Configure URLs (urls.py in blog_project)
from django.contrib import admin
from django.urls import path, include
urlpatterns = [
path('admin/', admin.site.urls),
path('tinymce/', include('tinymce.urls')), # TinyMCE URLs
path('', include('blog.urls')), # Include blog app URLs
]
Defining the Blog Post Model
In models.py
of the blog app:
from django.db import models
from django.contrib.auth.models import User
from tinymce.models import HTMLField
class Post(models.Model):
title = models.CharField(max_length=255)
content = HTMLField()
author = models.ForeignKey(User, on_delete=models.CASCADE)
created_at = models.DateTimeField(auto_now_add=True)
updated_at = models.DateTimeField(auto_now=True)
def __str__(self):
return self.title
Registering the Model in Admin
In admin.py
:
from django.contrib import admin
from .models import Post
admin.site.register(Post)
Creating Blog Views
In views.py
:
from django.shortcuts import render, get_object_or_404, redirect
from django.contrib.auth.decorators import login_required
from .models import Post
from .forms import PostForm
def post_list(request):
posts = Post.objects.all().order_by('-created_at')
return render(request, 'blog/post_list.html', {'posts': posts})
def post_detail(request, pk):
post = get_object_or_404(Post, pk=pk)
return render(request, 'blog/post_detail.html', {'post': post})
@login_required
def post_create(request):
if request.method == "POST":
form = PostForm(request.POST)
if form.is_valid():
post = form.save(commit=False)
post.author = request.user
post.save()
return redirect('post_detail', pk=post.pk)
else:
form = PostForm()
return render(request, 'blog/post_form.html', {'form': form})
@login_required
def post_edit(request, pk):
post = get_object_or_404(Post, pk=pk)
if request.method == "POST":
form = PostForm(request.POST, instance=post)
if form.is_valid():
form.save()
return redirect('post_detail', pk=post.pk)
else:
form = PostForm(instance=post)
return render(request, 'blog/post_form.html', {'form': form})
@login_required
def post_delete(request, pk):
post = get_object_or_404(Post, pk=pk)
if request.method == "POST":
post.delete()
return redirect('post_list')
return render(request, 'blog/post_confirm_delete.html', {'post': post})
Creating Forms
In forms.py
:
from django import forms
from .models import Post
class PostForm(forms.ModelForm):
class Meta:
model = Post
fields = ['title', 'content']
Setting Up URLs
In urls.py
of the blog app:
from django.urls import path
from . import views
urlpatterns = [
path('', views.post_list, name='post_list'),
path('post/<int:pk>/', views.post_detail, name='post_detail'),
path('post/new/', views.post_create, name='post_create'),
path('post/edit/<int:pk>/', views.post_edit, name='post_edit'),
path('post/delete/<int:pk>/', views.post_delete, name='post_delete'),
]
Creating HTML Templates
Create a templates/blog/
directory and add the following files:
base.html
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>My Blog</title>
</head>
<body>
<h1><a href="/">My Blog</a></h1>
{% block content %}{% endblock %}
</body>
</html>
post_list.html
{{% extends "blog/base.html" %}
{% block content %}
<h2>Blog Posts</h2>
<a href="{% url 'post_create' %}">New Post</a>
{% for post in posts %}
<div>
<h3><a href="{% url 'post_detail' post.pk %}">{{ post.title }}</a></h3>
<p>By {{ post.author }} on {{ post.created_at }}</p>
</div>
{% endfor %}
{% endblock %}
post_detail.html
{% extends "blog/base.html" %}
{% block content %}
<h2>{{ post.title }}</h2>
<p>By {{ post.author }} on {{ post.created_at }}</p>
<div>{{ post.content|safe }}</div>
<a href="{% url 'post_edit' post.pk %}">Edit</a>
<form method="POST" action="{% url 'post_delete' post.pk %}">
{% csrf_token %}
<button type="submit">Delete</button>
</form>
{% endblock %}
post_form.html
{% extends "blog/base.html" %}
{% block content %}
<h2>Create/Edit Post</h2>
<form method="POST">
{% csrf_token %}
{{ form.media }}
{{ form.as_p }}
<button type="submit">Save</button>
</form>
{% endblock %}
Configuring Static Files and TinyMCE
Configure templates & Add the TinyMCE config in settings.py
:
TINYMCE_DEFAULT_CONFIG = {
'height': 360,
'width': '100%',
'plugins': 'advlist autolink lists link image charmap print preview anchor',
'toolbar': 'undo redo | styleselect | bold italic | alignleft aligncenter alignright alignjustify | outdent indent | link image',
}
LOGIN_URL = '/admin/login/'
LOGOUT_URL = '/admin/logout/'
Running Migrations
python manage.py makemigrations
python manage.py migrate
Creating a Superuser
python manage.py createsuperuser
Running the Server
python manage.py runserver
Conclusion
Congratulations! You have built a Django Blogging Application with TinyMCE integration, authentication, and CRUD functionality. You can now expand it by adding features like categories, comments, and user profiles.
Comments
You must be logged in to post a comment.
3 weeks, 1 day ago
Here is the link to the repository with Source Code: https://github.com/django-tutorial-dev/blogging-app.git