Chapter 13: Complete Blog System
13.3 Advanced Features
User System Integration
Integrate complete user system functionality:
python
# views.py (accounts app)
from django.shortcuts import render, redirect
from django.contrib.auth import login
from django.contrib.auth.decorators import login_required
from django.contrib.auth.views import LoginView, LogoutView
from django.contrib import messages
from django.views.generic import CreateView, DetailView, UpdateView
from django.urls import reverse_lazy
from django.contrib.auth.models import User
from .forms import UserRegistrationForm, UserProfileForm
from .models import UserProfile
class RegisterView(CreateView):
form_class = UserRegistrationForm
template_name = 'accounts/register.html'
success_url = reverse_lazy('blog:home')
def form_valid(self, form):
response = super().form_valid(form)
# Auto-login user
login(self.request, self.object)
messages.success(self.request, 'Registration successful! Welcome to join us.')
return response
class ProfileView(DetailView):
model = User
template_name = 'accounts/profile.html'
context_object_name = 'profile_user'
def get_object(self, queryset=None):
# If user is logged in, show own profile; otherwise show specified user's profile
if self.request.user.is_authenticated:
return self.request.user
return super().get_object(queryset)
class ProfileUpdateView(UpdateView):
model = User
form_class = UserProfileForm
template_name = 'accounts/profile_edit.html'
success_url = reverse_lazy('accounts:profile')
def get_object(self, queryset=None):
return self.request.user
def form_valid(self, form):
response = super().form_valid(form)
messages.success(self.request, 'Profile updated successfully!')
return response
# forms.py
from django import forms
from django.contrib.auth.forms import UserCreationForm
from django.contrib.auth.models import User
from .models import UserProfile
class UserRegistrationForm(UserCreationForm):
email = forms.EmailField(required=True)
class Meta:
model = User
fields = ("username", "email", "password1", "password2")
def save(self, commit=True):
user = super().save(commit=False)
user.email = self.cleaned_data["email"]
if commit:
user.save()
# Create user profile
UserProfile.objects.create(user=user)
return user
class UserProfileForm(forms.ModelForm):
# User basic information
first_name = forms.CharField(max_length=30, required=False)
last_name = forms.CharField(max_length=30, required=False)
email = forms.EmailField(required=False)
class Meta:
model = UserProfile
fields = ['bio', 'location', 'birth_date', 'website', 'avatar']
widgets = {
'bio': forms.Textarea(attrs={'class': 'form-control', 'rows': 4}),
'location': forms.TextInput(attrs={'class': 'form-control'}),
'birth_date': forms.DateInput(attrs={'class': 'form-control', 'type': 'date'}),
'website': forms.URLInput(attrs={'class': 'form-control'}),
'avatar': forms.FileInput(attrs={'class': 'form-control'}),
}
def __init__(self, *args, **kwargs):
super().__init__(*args, **kwargs)
# Initialize user basic information fields
if self.instance and self.instance.user:
self.fields['first_name'].initial = self.instance.user.first_name
self.fields['last_name'].initial = self.instance.user.last_name
self.fields['email'].initial = self.instance.user.email
def save(self, commit=True):
profile = super().save(commit=False)
# Save user basic information
user = profile.user
user.first_name = self.cleaned_data['first_name']
user.last_name = self.cleaned_data['last_name']
user.email = self.cleaned_data['email']
if commit:
user.save()
profile.save()
return profileRich Text Editor
Integrate rich text editor:
# Install django-ckeditor
# pip install django-ckeditor
# settings.py
INSTALLED_APPS = [
# ...
'ckeditor',
'ckeditor_uploader',
]
# CKEditor configuration
CKEDITOR_CONFIGS = {
'default': {
'toolbar': 'full',
'height': 300,
'width': '100%',
},
}
CKEDITOR_UPLOAD_PATH = "uploads/"
MEDIA_URL = '/media/'
MEDIA_ROOT = os.path.join(BASE_DIR, 'media')
# models.py
from ckeditor.fields import RichTextField
from ckeditor_uploader.fields import RichTextUploadingField
class Article(models.Model):
# ... other fields ...
content = RichTextUploadingField() # Use rich text editor
excerpt = RichTextField(blank=True, config_name='default')
# forms.py
from ckeditor.widgets import CKEditorWidget
class ArticleForm(forms.ModelForm):
class Meta:
model = Article
fields = ['title', 'category', 'tags', 'content', 'excerpt', 'featured_image', 'status']
widgets = {
'content': CKEditorWidget(config_name='default'),
'excerpt': CKEditorWidget(config_name='default'),
# ... other widgets ...
}Cache Optimization
Implement cache optimization:
# settings.py
CACHES = {
'default': {
'BACKEND': 'django.core.cache.backends.redis.RedisCache',
'LOCATION': 'redis://127.0.0.1:6379/1',
}
}
# views.py
from django.views.decorators.cache import cache_page
from django.utils.decorators import method_decorator
from django.core.cache import cache
@method_decorator(cache_page(60 * 15), name='dispatch') # Cache for 15 minutes
class ArticleListView(ListView):
# ... view code ...
class ArticleDetailView(DetailView):
# ... other code ...
def get_object(self, queryset=None):
# Use cache to get article
slug = self.kwargs['slug']
cache_key = f'article_{slug}'
article = cache.get(cache_key)
if article is None:
article = super().get_object(queryset)
# Cache article for 1 hour
cache.set(cache_key, article, 60 * 60)
else:
# If retrieved from cache, still need to increase view count
article.view_count += 1
article.save(update_fields=['view_count'])
return article
# Use template fragment caching
# templates/blog/article_list.html
{% load cache %}
{% cache 900 article_list page_obj.number %}
{% for article in articles %}
<!-- Article list content -->
{% endfor %}
{% endcache %}
# Cache sidebar in template
{% cache 1800 sidebar %}
<!-- Sidebar content -->
{% endcache %}SEO Optimization
Implement SEO optimization features:
# models.py
class Article(models.Model):
# ... other fields ...
meta_description = models.TextField(blank=True, help_text="SEO description")
meta_keywords = models.CharField(max_length=255, blank=True, help_text="SEO keywords")
def get_meta_description(self):
"""Get SEO description"""
if self.meta_description:
return self.meta_description
# If not set, use article excerpt
return self.excerpt
def get_meta_keywords(self):
"""Get SEO keywords"""
if self.meta_keywords:
return self.meta_keywords
# If not set, use tag names
return ', '.join([tag.name for tag in self.tags.all()])
# templates/base.html
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>{% block title %}My Blog{% endblock %}</title>
<!-- SEO metadata -->
<meta name="description" content="{% block meta_description %}{% endblock %}">
<meta name="keywords" content="{% block meta_keywords %}{% endblock %}">
<meta name="author" content="{% block author %}{% endblock %}">
<!-- Open Graph -->
<meta property="og:title" content="{% block og_title %}{% endblock %}">
<meta property="og:description" content="{% block og_description %}{% endblock %}">
<meta property="og:type" content="article">
<meta property="og:url" content="{{ request.build_absolute_uri }}">
<!-- Twitter Card -->
<meta name="twitter:card" content="summary">
<meta name="twitter:title" content="{% block twitter_title %}{% endblock %}">
<meta name="twitter:description" content="{% block twitter_description %}{% endblock %}">
<link rel="canonical" href="{{ request.build_absolute_uri }}">
</head>
<body>
<!-- Page content -->
</body>
</html>
# templates/blog/article_detail.html
{% extends 'base.html' %}
{% block title %}{{ article.title }} - My Blog{% endblock %}
{% block meta_description %}{{ article.get_meta_description }}{% endblock %}
{% block meta_keywords %}{{ article.get_meta_keywords }}{% endblock %}
{% block author %}{{ article.author.get_full_name|default:article.author.username }}{% endblock %}
{% block og_title %}{{ article.title }}{% endblock %}
{% block og_description %}{{ article.get_meta_description }}{% endblock %}
{% block twitter_title %}{{ article.title }}{% endblock %}
{% block twitter_description %}{{ article.get_meta_description }}{% endblock %}With the implementation of these advanced features, the blog system will have complete user management, rich text editing, performance optimization, and SEO optimization capabilities.
Summary
Key points in implementing blog system advanced features:
- ✅ Integrate complete user registration, login, and profile management functions
- ✅ Integrate rich text editor to enhance content creation experience
- ✅ Implement cache optimization strategies to improve system performance
- ✅ Implement SEO optimization features to improve search engine visibility
- ✅ Focus on user experience and system maintainability
These advanced features make the blog system more complete and professional.
Next Article
We will learn about using Django REST Framework.
14.1 Django REST Framework Introduction →