Django project to create a Comments System
We will build a straightforward Django app where users can view posts and add comments, all using just two simple templates. We will learn how to set up models, handle form submissions and create clean views to power an interactive comment system. It’s perfect for getting a solid foundation with Django’s core features while keeping things neat and minimal.
Set Up Your Django Project and App
Prerequisites:
Open your terminal or command prompt and run:
django-admin startproject comment_project
cd comment_project
python manage.py startapp comments
Explanation:
- comment_project is your main Django project folder.
- comments is the app dedicated to handling posts and comments, keeping your code modular and organized.
Configure Your Project Settings
Open comment_project/settings.py and add the comments app to your installed apps:
INSTALLED_APPS = [
# Default Django apps
'django.contrib.admin',
'django.contrib.auth',
'django.contrib.contenttypes',
'django.contrib.sessions',
'django.contrib.messages',
'django.contrib.staticfiles',# Our custom app
'comments',
]
Define Models for Posts and Comments
Edit comments/models.py to add two models: Post and Comment.
from django.db import models
from django.contrib.auth.models import User
from django.utils import timezone
class Post(models.Model):
title = models.CharField(max_length=100)
content = models.TextField()
date_posted = models.DateTimeField(default=timezone.now)
author = models.ForeignKey(User, on_delete=models.CASCADE)
def __str__(self):
return self.title
class Comment(models.Model):
post = models.ForeignKey(Post, related_name='comments', on_delete=models.CASCADE)
user = models.ForeignKey(User, on_delete=models.CASCADE)
content = models.TextField()
date_posted = models.DateTimeField(default=timezone.now)
def __str__(self):
return f'Comment by {self.user.username} on "{self.post.title}"'
Explanation:
- The Post model stores each post's title, content, timestamp and author (linked to Django’s built-in User model).
- The Comment model links each comment to a Post and a User, stores the comment text and timestamp.
- related_name='comments' allows you to access comments for a post via post.comments.all().
Create the Database Tables
Run migrations to create the corresponding tables in the database:
python manage.py makemigrations
python manage.py migrate
Register Models with the Admin Interface
Register your models in comments/admin.py to manage posts and comments via the admin panel:
from django.contrib import admin
from .models import Post, Comment
@admin.register(Post)
class PostAdmin(admin.ModelAdmin):
list_display = ('title', 'author', 'date_posted')
search_fields = ('title', 'content', 'author__username')
@admin.register(Comment)
class CommentAdmin(admin.ModelAdmin):
list_display = ('post', 'user', 'date_posted')
search_fields = ('content', 'user__username', 'post__title')
Create a Comment Form
Create comments/forms.py:
from django import forms
from .models import Comment
class CommentForm(forms.ModelForm):
content = forms.CharField(
label='',
widget=forms.Textarea(attrs={
'rows': 3,
'placeholder': 'Write your comment here...'
})
)
class Meta:
model = Comment
fields = ['content']
Explanation: The form renders a textarea without a label and includes a placeholder for user guidance.
Implement Views
Edit comments/views.py:
from django.shortcuts import render, get_object_or_404, redirect
from .models import Post
from .forms import CommentForm
def home(request):
posts = Post.objects.all().order_by('-date_posted')
return render(request, 'comments/home.html', {'posts': posts})
def post_detail(request, pk):
post = get_object_or_404(Post, pk=pk)
comments = post.comments.all().order_by('-date_posted')
if request.method == 'POST':
form = CommentForm(request.POST)
if form.is_valid():
comment = form.save(commit=False)
comment.post = post
comment.user = request.user
comment.save()
return redirect('post_detail', pk=post.pk)
else:
form = CommentForm()
return render(request, 'comments/post_detail.html', {
'post': post,
'comments': comments,
'form': form,
})
Explanation:
- home fetches all posts ordered by newest first and renders the homepage.
- post_detail shows a single post with its comments, handles the comment form submission and refreshes the page after posting a comment.
Configure URLs
Create comments/urls.py:
from django.urls import path
from . import views
urlpatterns = [
path('', views.home, name='home'),
path('post/<int:pk>/', views.post_detail, name='post_detail'),
]
Include this in your main project URL config comment_project/urls.py:
from django.contrib import admin
from django.urls import path, include
urlpatterns = [
path('admin/', admin.site.urls),
path('', include('comments.urls')),
]
Create Templates
Create the directory structure:
comments/
└── templates/
└── comments/
├── home.html
└── post_detail.html
home.html:
<!DOCTYPE html>
<html>
<head>
<title>All Posts</title>
</head>
<body>
<h1>All Posts</h1>
<ul>
{% for post in posts %}
<li>
<a href="{% url 'post_detail' post.pk %}">{{ post.title }}</a> by {{ post.author.username }}
</li>
{% empty %}
<li>No posts available.</li>
{% endfor %}
</ul>
</body>
</html>
post_detail.html:
<!DOCTYPE html>
<html>
<head>
<title>{{ post.title }}</title>
</head>
<body>
<h1>{{ post.title }}</h1>
<p>{{ post.content }}</p>
<p>Posted by {{ post.author.username }} on {{ post.date_posted }}</p>
<h2>Comments</h2>
<form method="POST">
{% csrf_token %}
{{ form.as_p }}
<button type="submit">Add Comment</button>
</form>
<ul>
{% for comment in comments %}
<li><strong>{{ comment.user.username }}</strong>: {{ comment.content }} ({{ comment.date_posted }})</li>
{% empty %}
<li>No comments yet.</li>
{% endfor %}
</ul>
<a href="{% url 'home' %}">Back to All Posts</a>
</body>
</html>
Create a Superuser and Run the Server
Create a superuser to add initial posts via the admin panel:
python manage.py createsuperuser
Start the development server:
python manage.py runserver
Visit http://127.0.0.1:8000/admin/ and log in to create posts.
Visit http://127.0.0.1:8000/ to see all posts.

Click a post title to view and add comments.
