Skip to content

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 profile

Rich 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:

  1. ✅ Integrate complete user registration, login, and profile management functions
  2. ✅ Integrate rich text editor to enhance content creation experience
  3. ✅ Implement cache optimization strategies to improve system performance
  4. ✅ Implement SEO optimization features to improve search engine visibility
  5. ✅ 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 →

Directory

Return to Course Directory

Released under the [BY-NC-ND License](https://creativecommons.org/licenses/by-nc-nd/4.0/deed.en).