每天40分玩转Django:Django类视图

Django类视图

一、今日学习内容概述

学习模块 重要程度 主要内容
类视图基础 ⭐⭐⭐⭐⭐ View类、URLconf配置
通用视图 ⭐⭐⭐⭐⭐ ListView、DetailView等
Mixin机制 ⭐⭐⭐⭐ 多重继承、功能组合
自定义类视图 ⭐⭐⭐⭐ 视图定制、方法重写

二、类视图基础

2.1 基本类视图

python 复制代码
# 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配置

python 复制代码
# 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 列表视图和详情视图

python 复制代码
# 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 创建和编辑视图

python 复制代码
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机制实现

python 复制代码
# 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 自定义视图组合

python 复制代码
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 表单处理视图

python 复制代码
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)

七、类视图最佳实践

  1. 视图分组和组织
python 复制代码
# 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:
    """归档相关视图"""
  1. 通用功能抽象
python 复制代码
class BaseView(View):
    """基础视图类,包含通用功能"""
    def dispatch(self, request, *args, **kwargs):
        # 添加通用处理逻辑
        return super().dispatch(request, *args, **kwargs)

class BaseCRUDView(BaseView):
    """CRUD操作基础视图"""
    model = None
    form_class = None
  1. 权限控制
python 复制代码
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)

八、测试类视图

python 复制代码
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)

通过本章学习,你应该能够:

  1. 理解类视图的工作原理
  2. 使用Django的通用视图
  3. 创建自定义类视图
  4. 使用Mixin机制扩展功能

怎么样今天的内容还满意吗?再次感谢朋友们的观看,关注GZH:凡人的AI工具箱,回复666,送您价值199的AI大礼包。最后,祝您早日实现财务自由,还请给个赞,谢谢!

相关推荐
m0_748254664 分钟前
MySQL和SQL server的区别
数据库·mysql
秦南北5 分钟前
国内领先的宠物类电商代运营公司品融电商
大数据·人工智能·电商
补三补四6 分钟前
Yashan DB 实例
数据库·oracle·dba
计算机-秋大田8 分钟前
基于Spring Boot的宠物健康顾问系统的设计与实现(LW+源码+讲解)
java·vue.js·spring boot·后端·课程设计
uhakadotcom19 分钟前
OpenHands:AI 驱动的软件开发框架
后端·面试·github
龚大龙20 分钟前
机器学习(李宏毅)——Domain Adaptation
人工智能·机器学习
sanzk25 分钟前
以太网通讯
sqlite
vortex526 分钟前
在Kali中使用虚拟环境安装python工具的最佳实践:以 pwncat 为例
linux·python·网络安全·渗透测试·pip·kali
源码姑娘27 分钟前
基于DeepSeek的智慧医药系统(源码+部署教程)
java·人工智能·程序人生·毕业设计·springboot·健康医疗·课程设计
uhakadotcom33 分钟前
FinGPT:金融领域的开源语言模型框架
后端·面试·github