Labs ICT
Pro Login

Practical Example: Blog App

Building a complete blog with models, views, and templates.

Building a Complete Blog

Let's tie everything together by building a practical blog application from scratch. This example covers models, views, templates, forms, and admin — the core of any Django project. By the end, you'll have a working blog you can extend.

We'll keep it simple but realistic. A blog needs posts, categories, and comments. We'll use class-based views because they're efficient and follow Django conventions.

The Models

Every blog starts with its data. Our Post model stores the title, content, author, and publication status. Category organizes posts, and Comment lets readers interact.

from django.db import models
from django.contrib.auth.models import User

class Category(models.Model):
    name = models.CharField(max_length=100)
    slug = models.SlugField(unique=True)

    def __str__(self):
        return self.name

class Post(models.Model):
    title = models.CharField(max_length=200)
    slug = models.SlugField(unique=True)
    author = models.ForeignKey(User, on_delete=models.CASCADE)
    category = models.ForeignKey(Category, on_delete=models.SET_NULL, null=True)
    content = models.TextField()
    published = models.BooleanField(default=False)
    created_at = models.DateTimeField(auto_now_add=True)
    updated_at = models.DateTimeField(auto_now=True)

    def __str__(self):
        return self.title

class Comment(models.Model):
    post = models.ForeignKey(Post, on_delete=models.CASCADE, related_name='comments')
    name = models.CharField(max_length=100)
    body = models.TextField()
    created_at = models.DateTimeField(auto_now_add=True)

    def __str__(self):
        return f'{self.name} on {self.post.title}'

Notice the related_name='comments' on Comment. This lets you access comments from a post instance with post.comments.all(), which is much cleaner than filtering manually.

The Views

We'll use Django's generic class-based views for the standard operations. ListView shows published posts, DetailView shows a single post with its comments, and CreateView handles new comments.

from django.views.generic import ListView, DetailView, CreateView
from django.urls import reverse_lazy
from .models import Post, Comment
from .forms import CommentForm

class PostListView(ListView):
    model = Post
    template_name = 'blog/post_list.html'
    context_object_name = 'posts'

    def get_queryset(self):
        return Post.objects.filter(published=True).order_by('-created_at')

class PostDetailView(DetailView):
    model = Post
    template_name = 'blog/post_detail.html'

    def get_context_data(self, **kwargs):
        context = super().get_context_data(**kwargs)
        context['form'] = CommentForm()
        return context

class CommentCreateView(CreateView):
    model = Comment
    form_class = CommentForm
    template_name = 'blog/post_detail.html'

    def form_valid(self, form):
        form.instance.post = Post.objects.get(pk=self.kwargs['pk'])
        return super().form_valid(form)

    def get_success_url(self):
        return reverse_lazy('post_detail', kwargs={'pk': self.kwargs['pk']})
Try it Yourself →

Templates and Admin

Create templates that extend your base layout. The post list displays cards with titles and excerpts. The detail view shows full content, the comment form, and existing comments.

from django.contrib import admin
from .models import Post, Category, Comment

@admin.register(Post)
class PostAdmin(admin.ModelAdmin):
    list_display = ('title', 'author', 'category', 'published', 'created_at')
    list_filter = ('published', 'category')
    prepopulated_fields = {'slug': ('title',)}

admin.site.register(Category)
admin.site.register(Comment)

With list_display and list_filter, your admin becomes a powerful management interface. The prepopulated_fields feature auto-fills the slug from the title, saving you manual work.

Putting It All Together

Wire up your URLs, register the models in admin, run migrations, and you have a complete blog. This pattern — models for data, views for logic, templates for presentation, admin for management — is the foundation of every Django project.

From here, you could add user authentication for authors, pagination on the post list, search functionality, or an RSS feed. The blog is a perfect starting point because it touches every part of Django.