每天40分玩转Django:Django类视图
Django类视图
一、今日学习内容概述
学习模块 | 重要程度 | 主要内容 |
---|---|---|
类视图基础 | ⭐⭐⭐⭐⭐ | View类、URLconf配置 |
通用视图 | ⭐⭐⭐⭐⭐ | ListView、DetailView等 |
Mixin机制 | ⭐⭐⭐⭐ | 多重继承、功能组合 |
自定义类视图 | ⭐⭐⭐⭐ | 视图定制、方法重写 |
二、类视图基础
2.1 基本类视图
# views.py
from django.views import View
from django.http import HttpResponse
from django.shortcuts import render
class HelloView(View):
def get(self, request, *args, **kwargs):
return HttpResponse('Hello, World!')
class HomeView(View):
template_name = 'home.html'
def get(self, request):
context = {
'title': '首页',
'message': '欢迎访问'
}
return render(request, self.template_name, context)
def post(self, request):
# 处理POST请求
data = request.POST.get('data')
# 处理数据...
return HttpResponse('数据已处理')
2.2 URL配置
# urls.py
from django.urls import path
from .views import HelloView, HomeView
urlpatterns = [
path('hello/', HelloView.as_view(), name='hello'),
path('', HomeView.as_view(), name='home'),
]
三、通用类视图实现
3.1 列表视图和详情视图
# models.py
from django.db import models
class Article(models.Model):
title = models.CharField('标题', max_length=200)
content = models.TextField('内容')
created_at = models.DateTimeField('创建时间', auto_now_add=True)
updated_at = models.DateTimeField('更新时间', auto_now=True)
author = models.ForeignKey('auth.User', on_delete=models.CASCADE)
def __str__(self):
return self.title
# views.py
from django.views.generic import ListView, DetailView
from .models import Article
class ArticleListView(ListView):
model = Article
template_name = 'blog/article_list.html'
context_object_name = 'articles'
paginate_by = 10
def get_queryset(self):
queryset = super().get_queryset()
return queryset.select_related('author')
def get_context_data(self, **kwargs):
context = super().get_context_data(**kwargs)
context['total_articles'] = self.get_queryset().count()
return context
class ArticleDetailView(DetailView):
model = Article
template_name = 'blog/article_detail.html'
context_object_name = 'article'
def get_context_data(self, **kwargs):
context = super().get_context_data(**kwargs)
# 添加相关文章
context['related_articles'] = Article.objects.filter(
author=self.object.author
).exclude(id=self.object.id)[:5]
return context
3.2 创建和编辑视图
from django.views.generic.edit import CreateView, UpdateView, DeleteView
from django.contrib.auth.mixins import LoginRequiredMixin
from django.urls import reverse_lazy
class ArticleCreateView(LoginRequiredMixin, CreateView):
model = Article
template_name = 'blog/article_form.html'
fields = ['title', 'content']
success_url = reverse_lazy('article_list')
def form_valid(self, form):
form.instance.author = self.request.user
return super().form_valid(form)
class ArticleUpdateView(LoginRequiredMixin, UpdateView):
model = Article
template_name = 'blog/article_form.html'
fields = ['title', 'content']
def get_queryset(self):
# 只允许作者编辑自己的文章
return super().get_queryset().filter(author=self.request.user)
def get_success_url(self):
return reverse_lazy('article_detail', kwargs={'pk': self.object.pk})
class ArticleDeleteView(LoginRequiredMixin, DeleteView):
model = Article
template_name = 'blog/article_confirm_delete.html'
success_url = reverse_lazy('article_list')
四、Mixin机制实现
# mixins.py
from django.contrib import messages
from django.shortcuts import redirect
class AuthorRequiredMixin:
"""确保只有作者可以编辑内容"""
def dispatch(self, request, *args, **kwargs):
obj = self.get_object()
if obj.author != request.user:
messages.error(request, '您没有权限执行此操作')
return redirect('article_list')
return super().dispatch(request, *args, **kwargs)
class TitleSearchMixin:
"""添加标题搜索功能"""
def get_queryset(self):
queryset = super().get_queryset()
search_query = self.request.GET.get('search')
if search_query:
queryset = queryset.filter(title__icontains=search_query)
return queryset
def get_context_data(self, **kwargs):
context = super().get_context_data(**kwargs)
context['search_query'] = self.request.GET.get('search', '')
return context
# 使用Mixin
class ArticleListView(TitleSearchMixin, ListView):
model = Article
template_name = 'blog/article_list.html'
context_object_name = 'articles'
paginate_by = 10
class ArticleUpdateView(LoginRequiredMixin, AuthorRequiredMixin, UpdateView):
model = Article
template_name = 'blog/article_form.html'
fields = ['title', 'content']
五、类视图流程图
六、高级类视图示例
6.1 自定义视图组合
from django.views.generic import TemplateView
from django.views.generic.dates import (
YearArchiveView,
MonthArchiveView,
DayArchiveView
)
class ArticleArchiveView(TemplateView):
template_name = 'blog/article_archive.html'
def get_context_data(self, **kwargs):
context = super().get_context_data(**kwargs)
context['years'] = Article.objects.dates('created_at', 'year', order='DESC')
return context
class ArticleYearArchiveView(YearArchiveView):
model = Article
date_field = 'created_at'
make_object_list = True
template_name = 'blog/article_archive_year.html'
class ArticleMonthArchiveView(MonthArchiveView):
model = Article
date_field = 'created_at'
template_name = 'blog/article_archive_month.html'
6.2 表单处理视图
from django.views.generic.edit import FormView
from django import forms
class ContactForm(forms.Form):
name = forms.CharField(max_length=100)
email = forms.EmailField()
message = forms.CharField(widget=forms.Textarea)
class ContactView(FormView):
template_name = 'contact.html'
form_class = ContactForm
success_url = '/thanks/'
def form_valid(self, form):
# 发送邮件
name = form.cleaned_data['name']
email = form.cleaned_data['email']
message = form.cleaned_data['message']
# 处理表单数据...
messages.success(self.request, '消息已发送')
return super().form_valid(form)
七、类视图最佳实践
- 视图分组和组织
# views/__init__.py
from .article import ArticleListView, ArticleDetailView
from .archive import ArticleArchiveView
from .contact import ContactView
# views/article.py
class ArticleViews:
"""文章相关视图"""
# views/archive.py
class ArchiveViews:
"""归档相关视图"""
- 通用功能抽象
class BaseView(View):
"""基础视图类,包含通用功能"""
def dispatch(self, request, *args, **kwargs):
# 添加通用处理逻辑
return super().dispatch(request, *args, **kwargs)
class BaseCRUDView(BaseView):
"""CRUD操作基础视图"""
model = None
form_class = None
- 权限控制
from django.contrib.auth.mixins import (
LoginRequiredMixin,
PermissionRequiredMixin
)
class StaffRequiredMixin(LoginRequiredMixin):
"""要求用户是员工"""
def dispatch(self, request, *args, **kwargs):
if not request.user.is_staff:
messages.error(request, '需要员工权限')
return redirect('home')
return super().dispatch(request, *args, **kwargs)
八、测试类视图
from django.test import TestCase, Client
from django.urls import reverse
from django.contrib.auth.models import User
class ArticleViewTests(TestCase):
def setUp(self):
self.client = Client()
self.user = User.objects.create_user(
username='testuser',
password='testpass123'
)
def test_article_list_view(self):
response = self.client.get(reverse('article_list'))
self.assertEqual(response.status_code, 200)
self.assertTemplateUsed(response, 'blog/article_list.html')
def test_article_create_view(self):
# 未登录用户
response = self.client.get(reverse('article_create'))
self.assertEqual(response.status_code, 302) # 重定向到登录页
# 登录用户
self.client.login(username='testuser', password='testpass123')
response = self.client.get(reverse('article_create'))
self.assertEqual(response.status_code, 200)
通过本章学习,你应该能够:
- 理解类视图的工作原理
- 使用Django的通用视图
- 创建自定义类视图
- 使用Mixin机制扩展功能
怎么样今天的内容还满意吗?再次感谢朋友们的观看,关注GZH:凡人的AI工具箱,回复666,送您价值199的AI大礼包。最后,祝您早日实现财务自由,还请给个赞,谢谢!