Chapter 13: Complete Blog System
13.2 Core Function Implementation
Article CRUD
Implement article create, read, update, delete functions:
python
# views.py
from django.shortcuts import render, get_object_or_404, redirect
from django.contrib.auth.decorators import login_required
from django.contrib.auth.mixins import LoginRequiredMixin
from django.views.generic import ListView, DetailView, CreateView, UpdateView, DeleteView
from django.urls import reverse_lazy
from django.contrib import messages
from .models import Article, Category, Tag
from .forms import ArticleForm
class ArticleListView(ListView):
model = Article
template_name = 'blog/article_list.html'
context_object_name = 'articles'
paginate_by = 10
def get_queryset(self):
return Article.objects.filter(status='published').select_related('author', 'category')
def get_context_data(self, **kwargs):
context = super().get_context_data(**kwargs)
context['categories'] = Category.objects.all()
context['tags'] = Tag.objects.all()
return context
class ArticleDetailView(DetailView):
model = Article
template_name = 'blog/article_detail.html'
context_object_name = 'article'
def get_queryset(self):
return Article.objects.select_related('author', 'category').prefetch_related('tags')
def get_object(self, queryset=None):
article = super().get_object(queryset)
# Increase view count
article.view_count += 1
article.save(update_fields=['view_count'])
return article
def get_context_data(self, **kwargs):
context = super().get_context_data(**kwargs)
# Get related articles
context['related_articles'] = Article.objects.filter(
category=self.object.category,
status='published'
).exclude(pk=self.object.pk)[:5]
return context
class ArticleCreateView(LoginRequiredMixin, CreateView):
model = Article
form_class = ArticleForm
template_name = 'blog/article_form.html'
def form_valid(self, form):
form.instance.author = self.request.user
response = super().form_valid(form)
messages.success(self.request, 'Article created successfully!')
return response
class ArticleUpdateView(LoginRequiredMixin, UpdateView):
model = Article
form_class = ArticleForm
template_name = 'blog/article_form.html'
def get_queryset(self):
# Users can only edit their own articles
return Article.objects.filter(author=self.request.user)
def form_valid(self, form):
response = super().form_valid(form)
messages.success(self.request, 'Article updated successfully!')
return response
class ArticleDeleteView(LoginRequiredMixin, DeleteView):
model = Article
template_name = 'blog/article_confirm_delete.html'
success_url = reverse_lazy('blog:article_list')
def get_queryset(self):
# Users can only delete their own articles
return Article.objects.filter(author=self.request.user)
def delete(self, request, *args, **kwargs):
messages.success(self.request, 'Article deleted successfully!')
return super().delete(request, *args, **kwargs)
# forms.py
from django import forms
from .models import Article, Category, Tag
class ArticleForm(forms.ModelForm):
class Meta:
model = Article
fields = ['title', 'category', 'tags', 'content', 'excerpt', 'featured_image', 'status']
widgets = {
'title': forms.TextInput(attrs={'class': 'form-control'}),
'category': forms.Select(attrs={'class': 'form-control'}),
'tags': forms.SelectMultiple(attrs={'class': 'form-control'}),
'content': forms.Textarea(attrs={'class': 'form-control', 'rows': 15}),
'excerpt': forms.Textarea(attrs={'class': 'form-control', 'rows': 3}),
'featured_image': forms.FileInput(attrs={'class': 'form-control'}),
'status': forms.Select(attrs={'class': 'form-control'}),
}
def __init__(self, *args, **kwargs):
super().__init__(*args, **kwargs)
self.fields['tags'].widget.attrs.update({'size': '10'})Categories and Tags
Implement category and tag functions:
python
# views.py
class CategoryDetailView(ListView):
model = Article
template_name = 'blog/category_detail.html'
context_object_name = 'articles'
paginate_by = 10
def get_queryset(self):
self.category = get_object_or_404(Category, slug=self.kwargs['slug'])
return Article.objects.filter(
category=self.category,
status='published'
).select_related('author', 'category')
def get_context_data(self, **kwargs):
context = super().get_context_data(**kwargs)
context['category'] = self.category
return context
class TagDetailView(ListView):
model = Article
template_name = 'blog/tag_detail.html'
context_object_name = 'articles'
paginate_by = 10
def get_queryset(self):
self.tag = get_object_or_404(Tag, slug=self.kwargs['slug'])
return Article.objects.filter(
tags=self.tag,
status='published'
).select_related('author', 'category')
def get_context_data(self, **kwargs):
context = super().get_context_data(**kwargs)
context['tag'] = self.tag
return contextComment System
Implement comment function:
python
# models.py
class Comment(models.Model):
article = models.ForeignKey(Article, on_delete=models.CASCADE, related_name='comments')
author = models.ForeignKey(User, on_delete=models.CASCADE, related_name='comments')
parent = models.ForeignKey('self', on_delete=models.CASCADE, null=True, blank=True, related_name='replies')
content = models.TextField()
is_approved = models.BooleanField(default=True)
created_at = models.DateTimeField(auto_now_add=True)
class Meta:
ordering = ['created_at']
def __str__(self):
return f'{self.author.username}\'s comment on {self.article.title}'
# forms.py
class CommentForm(forms.ModelForm):
class Meta:
model = Comment
fields = ['content']
widgets = {
'content': forms.Textarea(attrs={'class': 'form-control', 'rows': 4, 'placeholder': 'Please enter your comment...'}),
}
# views.py
from django.contrib.auth.decorators import login_required
from django.http import JsonResponse
@login_required
def add_comment(request, article_id):
article = get_object_or_404(Article, id=article_id)
if request.method == 'POST':
form = CommentForm(request.POST)
if form.is_valid():
comment = form.save(commit=False)
comment.article = article
comment.author = request.user
comment.save()
messages.success(request, 'Comment posted successfully!')
return redirect('blog:article_detail', slug=article.slug)
return redirect('blog:article_detail', slug=article.slug)
class ArticleDetailView(DetailView):
# ... other code ...
def get_context_data(self, **kwargs):
context = super().get_context_data(**kwargs)
# Get comments
context['comments'] = self.object.comments.filter(
is_approved=True,
parent=None
).select_related('author').prefetch_related('replies__author')
context['comment_form'] = CommentForm()
return contextSearch Function
Implement article search function:
python
# views.py
from django.db.models import Q
class SearchView(ListView):
model = Article
template_name = 'blog/search_results.html'
context_object_name = 'articles'
paginate_by = 10
def get_queryset(self):
query = self.request.GET.get('q')
if query:
return Article.objects.filter(
Q(title__icontains=query) |
Q(content__icontains=query) |
Q(excerpt__icontains=query)
).filter(status='published').select_related('author', 'category').distinct()
return Article.objects.none()
def get_context_data(self, **kwargs):
context = super().get_context_data(**kwargs)
context['query'] = self.request.GET.get('q', '')
return contextSummary
Key points in implementing blog system core functions:
- ✅ Use Django's generic views to simplify CRUD operations
- ✅ Implement article category and tag display functions
- ✅ Build a complete comment system with reply support
- ✅ Develop efficient search functions
- ✅ Focus on user experience and data security
With the implementation of these core functions, the blog system already has basic usability.
Next Article
We will implement advanced features of the blog system.