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

news2025/1/6 21:56:24

Django类视图

一、知识要点概览表

类别知识点掌握程度要求
基础视图View、TemplateView、RedirectView深入理解
通用显示视图ListView、DetailView熟练应用
通用编辑视图CreateView、UpdateView、DeleteView熟练应用
Mixin机制ContextMixin、LoginRequiredMixin理解原理
视图配置URL配置、参数传递、模板指定熟练应用

二、基础视图实现

1. 基本View类

# 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, Class-based Views!")
    
    def post(self, request, *args, **kwargs):
        return HttpResponse("POST request received")

class DashboardView(View):
    template_name = 'dashboard.html'
    
    def get(self, request):
        context = {
            'username': request.user.username,
            'page_title': 'Dashboard'
        }
        return render(request, self.template_name, context)

2. TemplateView使用

# views.py
from django.views.generic import TemplateView

class HomePageView(TemplateView):
    template_name = "home.html"
    
    def get_context_data(self, **kwargs):
        context = super().get_context_data(**kwargs)
        context['page_title'] = '首页'
        context['features'] = [
            '基于类的视图',
            '通用视图',
            'Mixin机制'
        ]
        return context

3. RedirectView示例

# views.py
from django.views.generic import RedirectView

class GitHubRedirectView(RedirectView):
    url = 'https://github.com'
    permanent = False  # 使用302临时重定向
    query_string = True  # 保留查询字符串
    
class OldPostRedirectView(RedirectView):
    permanent = True  # 使用301永久重定向
    
    def get_redirect_url(self, *args, **kwargs):
        post_id = kwargs['post_id']
        return f'/blog/posts/{post_id}/'

三、通用显示视图

1. ListView实现

# 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)
    is_published = models.BooleanField(default=False)
    
    def __str__(self):
        return self.title

# views.py
from django.views.generic import ListView
from .models import Article

class ArticleListView(ListView):
    model = Article
    template_name = 'articles/article_list.html'
    context_object_name = 'articles'
    paginate_by = 10
    
    def get_queryset(self):
        """只显示已发布的文章"""
        return Article.objects.filter(
            is_published=True
        ).order_by('-created_at')
    
    def get_context_data(self, **kwargs):
        context = super().get_context_data(**kwargs)
        context['total_articles'] = self.get_queryset().count()
        return context

2. DetailView实现

# views.py
from django.views.generic import DetailView
from django.shortcuts import get_object_or_404

class ArticleDetailView(DetailView):
    model = Article
    template_name = 'articles/article_detail.html'
    context_object_name = 'article'
    
    def get_object(self, queryset=None):
        """自定义获取对象的方法"""
        obj = super().get_object(queryset=queryset)
        # 增加访问次数
        obj.views_count = obj.views_count + 1
        obj.save()
        return obj
    
    def get_context_data(self, **kwargs):
        context = super().get_context_data(**kwargs)
        # 添加相关文章
        context['related_articles'] = Article.objects.filter(
            is_published=True
        ).exclude(
            id=self.object.id
        )[:3]
        return context

四、通用编辑视图

1. CreateView实现

# forms.py
from django import forms
from .models import Article

class ArticleForm(forms.ModelForm):
    class Meta:
        model = Article
        fields = ['title', 'content', 'is_published']
        
    def clean_title(self):
        title = self.cleaned_data['title']
        if len(title) < 5:
            raise forms.ValidationError("标题长度不能少于5个字符")
        return title

# views.py
from django.views.generic.edit import CreateView
from django.urls import reverse_lazy
from .forms import ArticleForm

class ArticleCreateView(CreateView):
    model = Article
    form_class = ArticleForm
    template_name = 'articles/article_form.html'
    success_url = reverse_lazy('article_list')
    
    def form_valid(self, form):
        """表单验证成功时的处理"""
        form.instance.author = self.request.user
        response = super().form_valid(form)
        # 可以在这里添加额外的处理逻辑
        return response
        
    def get_initial(self):
        """设置表单初始值"""
        return {
            'title': '新文章',
            'is_published': False
        }

2. UpdateView实现

# views.py
from django.views.generic.edit import UpdateView
from django.contrib.auth.mixins import LoginRequiredMixin

class ArticleUpdateView(LoginRequiredMixin, UpdateView):
    model = Article
    form_class = ArticleForm
    template_name = 'articles/article_update.html'
    
    def get_success_url(self):
        return reverse_lazy(
            'article_detail',
            kwargs={'pk': self.object.pk}
        )
    
    def get_queryset(self):
        """确保用户只能编辑自己的文章"""
        return Article.objects.filter(author=self.request.user)

3. DeleteView实现

# views.py
from django.views.generic.edit import DeleteView
from django.urls import reverse_lazy
from django.contrib.auth.mixins import UserPassesTestMixin

class ArticleDeleteView(LoginRequiredMixin, UserPassesTestMixin, DeleteView):
    model = Article
    template_name = 'articles/article_confirm_delete.html'
    success_url = reverse_lazy('article_list')
    
    def test_func(self):
        """检查用户是否有权限删除文章"""
        article = self.get_object()
        return self.request.user == article.author
    
    def delete(self, request, *args, **kwargs):
        """自定义删除逻辑"""
        self.object = self.get_object()
        success_url = self.get_success_url()
        # 可以在这里添加其他清理工作
        self.object.delete()
        return HttpResponseRedirect(success_url)

五、类视图的URL配置

# urls.py
from django.urls import path
from . import views

app_name = 'articles'

urlpatterns = [
    path('', views.ArticleListView.as_view(), name='article_list'),
    path('<int:pk>/', views.ArticleDetailView.as_view(), name='article_detail'),
    path('create/', views.ArticleCreateView.as_view(), name='article_create'),
    path('<int:pk>/update/', views.ArticleUpdateView.as_view(), name='article_update'),
    path('<int:pk>/delete/', views.ArticleDeleteView.as_view(), name='article_delete'),
]

六、类视图执行流程图

在这里插入图片描述

七、Mixin的使用

1. 自定义Mixin

class TitleMixin:
    title = ''
    
    def get_context_data(self, **kwargs):
        context = super().get_context_data(**kwargs)
        context['title'] = self.title
        return context

class AuthorRequiredMixin:
    """确保用户是作者的Mixin"""
    def dispatch(self, request, *args, **kwargs):
        obj = self.get_object()
        if obj.author != request.user:
            raise PermissionDenied
        return super().dispatch(request, *args, **kwargs)

class PageTitleMixin:
    page_title = ''
    
    def get_context_data(self, **kwargs):
        context = super().get_context_data(**kwargs)
        context['page_title'] = self.page_title
        return context

# 使用Mixin
class ArticleDetailView(TitleMixin, PageTitleMixin, DetailView):
    model = Article
    template_name = 'articles/article_detail.html'
    title = '文章详情'
    page_title = '查看文章'

2. 常用Mixin组合

from django.contrib.auth.mixins import (
    LoginRequiredMixin,
    PermissionRequiredMixin
)

class ArticleAdminView(
    LoginRequiredMixin,
    PermissionRequiredMixin,
    ListView
):
    model = Article
    template_name = 'articles/admin_list.html'
    permission_required = 'articles.view_article'
    
    def get_queryset(self):
        return Article.objects.all().order_by('-created_at')

class StaffRequiredMixin(UserPassesTestMixin):
    def test_func(self):
        return self.request.user.is_staff

class ArticleStaffView(StaffRequiredMixin, ListView):
    model = Article
    template_name = 'articles/staff_list.html'

八、模板示例

<!-- templates/articles/article_list.html -->
{% extends 'base.html' %}

{% block content %}
<div class="container">
    <h1>{{ page_title }}</h1>
    
    <div class="article-list">
        {% for article in articles %}
        <div class="article-item">
            <h2>{{ article.title }}</h2>
            <p>{{ article.content|truncatewords:30 }}</p>
            <div class="article-meta">
                <span>作者: {{ article.author }}</span>
                <span>发布时间: {{ article.created_at|date:"Y-m-d" }}</span>
            </div>
            <div class="article-actions">
                <a href="{% url 'articles:article_detail' article.pk %}"
                   class="btn btn-primary">
                    查看详情
                </a>
                {% if user == article.author %}
                <a href="{% url 'articles:article_update' article.pk %}"
                   class="btn btn-secondary">
                    编辑
                </a>
                <a href="{% url 'articles:article_delete' article.pk %}"
                   class="btn btn-danger">
                    删除
                </a>
                {% endif %}
            </div>
        </div>
        {% empty %}
        <p>暂无文章</p>
        {% endfor %}
    </div>
    
    {% if is_paginated %}
    <nav aria-label="Page navigation">
        <ul class="pagination">
            {% if page_obj.has_previous %}
            <li class="page-item">
                <a class="page-link" href="?page={{ page_obj.previous_page_number }}">
                    上一页
                </a>
            </li>
            {% endif %}
            
            {% for num in page_obj.paginator.page_range %}
            <li class="page-item {% if page_obj.number == num %}active{% endif %}">
                <a class="page-link" href="?page={{ num }}">{{ num }}</a>
            </li>
            {% endfor %}
            
            {% if page_obj.has_next %}
            <li class="page-item">
                <a class="page-link" href="?page={{ page_obj.next_page_number }}">
                    下一页
                </a>
            </li>
            {% endif %}
        </ul>
    </nav>
    {% endif %}
</div>
{% endblock %}

这就是关于Django类视图的详细内容。通过学习这些内容,将能够理解和使用Django的类视图系统,实现更加优雅和可维护的视图逻辑。如果有任何问题,欢迎随时提出!


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

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.coloradmin.cn/o/2270424.html

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

PgSQL如何用cmd命令行备份和还原数据库

一、备份 备份为压缩的二进制格式&#xff08;通常更快且占用空间更少&#xff09; pg_dump -U username -Fc -h hostname -p port -d dbname -F p -f backup.sql-U username&#xff1a;指定连接数据库的用户名&#xff08;默认是 postgres&#xff09;。-Fc&#xff1a;备…

QT-------------多线程

实现思路 QThread 类简介&#xff1a; QThread 是 Qt 中用于多线程编程的基础类。可以通过继承 QThread 并重写 run() 方法来创建自定义的线程逻辑。新线程的执行从 run() 开始&#xff0c;调用 start() 方法启动线程。 掷骰子的多线程应用程序&#xff1a; 创建一个 DiceThre…

VBA批量插入图片到PPT,一页一图

Sub InsertPicturesIntoSlides()Dim pptApp As ObjectDim pptPres As ObjectDim pptSlide As ObjectDim strFolderPath As StringDim strFileName As StringDim i As Integer 设置图片文件夹路径strFolderPath "C:\您的图片文件夹路径\" 请替换为您的图片文件夹路径…

当知识图谱遇上文本智能处理,会擦出怎样的火花?

目前以理解人类语言为入口的认知智能成为了人工智能发展的突破点&#xff0c;而知识图谱则是迈向认知智能的关键要素。达观数据在2018AIIA人工智能开发者大会承办的语言认知智能与知识图谱公开课上&#xff0c;三位来自企业和学术领域的专家分别从不同角度讲述的知识图谱的应用…

数据挖掘——回归算法

数据挖掘——回归算法 回归算法线性回归最小二乘法优化求解——梯度下降法逻辑回归逻辑回归函数逻辑回归参数估计逻辑回归正则化 决策树回归小结 回归算法 回归分析 如果把其中的一些因素&#xff08;房屋面积&#xff09;作为自变量&#xff0c;而另一些随自变量的变化而变化…

Ubuntu 24.04 LTS 解决网络连接问题

1. 问题描述 现象&#xff1a;ens33 网络接口无法获取 IPv4 地址&#xff0c;导致网络不可用。初步排查&#xff1a; 运行 ip a&#xff0c;发现 ens33 接口没有分配 IPv4 地址。运行 ping www.baidu.com&#xff0c;提示“网络不可达”。查看 NetworkManager 日志&#xff0c…

spring-boot启动源码分析(二)之SpringApplicationRunListener

在上一篇《spring-boot启动源码分析&#xff08;一&#xff09;之SpringApplication实例构造》后&#xff0c;继续看了一个月的Spring boot启动源码&#xff0c;初步把流程看完了&#xff0c;接下来会不断输出总结&#xff0c;以巩固这段时间的学习。同时也希望能帮到同样感兴趣…

基于N-HiTS神经层次插值模型的时间序列预测——cross validation交叉验证与ray tune超参数优化

论文链接&#xff1a;https://arxiv.org/pdf/2201.12886v3 N-HiTS: Neural Hierarchical Interpolation for TimeSeries Forecasting \begin{aligned} &\text{\large \color{#CDA59E}N-HiTS: Neural Hierarchical Interpolation for TimeSeries Forecasting}\\ \end{aligne…

Lumos学习王佩丰Excel第二十三讲:Excel图表与PPT

一、双坐标柱形图的补充知识 1、主次坐标设置 2、主次坐标柱形避让&#xff08;通过增加两个系列&#xff0c;挤压使得两个柱形挨在一起&#xff09; 增加两个系列 将一个系列设置成主坐标轴&#xff0c;另一个设成次坐标轴 调整系列位置 二、饼图美化 1、饼图美化常见设置 …

YK人工智能(三)——万字长文学会torch深度学习

2.1 张量 本节主要内容&#xff1a; 张量的简介PyTorch如何创建张量PyTorch中张量的操作PyTorch中张量的广播机制 2.1.1 简介 几何代数中定义的张量是基于向量和矩阵的推广&#xff0c;比如我们可以将标量视为零阶张量&#xff0c;矢量可以视为一阶张量&#xff0c;矩阵就是…

Java基于SpringBoot的甘肃非物质文化网站的设计与实现,附源码

博主介绍&#xff1a;✌Java老徐、7年大厂程序员经历。全网粉丝12w、csdn博客专家、掘金/华为云/阿里云/InfoQ等平台优质作者、专注于Java技术领域和毕业项目实战✌ &#x1f345;文末获取源码联系&#x1f345; &#x1f447;&#x1f3fb; 精彩专栏推荐订阅&#x1f447;&…

计算机网络:网络层知识点及习题(一)

网课资源&#xff1a; 湖科大教书匠 1、概述 网络层实现主机到主机的传输&#xff0c;主要有分组转发和路由选择两大功能 路由选择处理机得出路由表&#xff0c;路由表再生成转发表&#xff0c;从而实现分组从不同的端口转发 网络层向上层提供的两种服务&#xff1a;面向连接…

ACL的注意事项

ACL只对数据进行抓取和匹配&#xff0c;ACl本身不对数据做拒绝和允许的操作&#xff0c;只有在接口方向上应用后才对数据进行拒绝或允许的操作。 ACl只在packetfilter包过滤时默认动作是允许&#xff0c;这个时候至少需要有一条deny规则&#xff0c;否则全都是允许的规则&…

【Cesium】九、Cesium点击地图获取点击位置的坐标,并在地图上添加图标

文章目录 一、前言二、实现方法三、App.vue 一、前言 查找发现好几种方法可以获取到点击位置的坐标。这里我实现需求就不深究学习了。将几位大佬的方法学习过来稍微整合了一下。 本文参考文章&#xff1a; cesium 4种拾取坐标的方法 【Cesium基础学习】拾取坐标 cesium拾取当…

OpenStack的核心组件、主要特点和使用场景

OpenStack 是一个开源的云计算平台&#xff0c;主要用于构建和管理公共及私有云环境。它由多个模块组成&#xff0c;提供虚拟化资源管理、存储管理、网络配置等功能&#xff0c;旨在为数据中心提供自动化的、灵活的云基础设施服务。OpenStack最初由NASA和Rackspace共同开发&…

51c自动驾驶~合集44

我自己的原文哦~ https://blog.51cto.com/whaosoft/12969097 #Towards Generalist Robot Policies 清华大学&字节 | 迈向通用机器人策略&#xff1a;如何选择VLA&#xff1f; 论文标题&#xff1a;Towards Generalist Robot Policies: What Matters in Building Vision…

17爬虫:关于DrissionPage相关内容的学习01

概述 前面我们已经大致了解了selenium的用法&#xff0c;DerssionPage同selenium一样&#xff0c;也是一个基于Python的网页自动化工具。 DrissionPage既可以实现网页的自动化操作&#xff0c;也能够实现收发数据包&#xff0c;也可以把两者的功能合二为一。 DressionPage的…

SSM-Spring-AOP

目录 1 AOP实现步骤&#xff08;以前打印当前系统的时间为例&#xff09; 2 AOP工作流程 3 AOP核心概念 4 AOP配置管理 4-1 AOP切入点表达式 4-1-1 语法格式 4-1-2 通配符 4-2 AOP通知类型 五种通知类型 AOP通知获取数据 获取参数 获取返回值 获取异常 总结 5 …

【Linux】:线程安全 + 死锁问题

&#x1f4c3;个人主页&#xff1a;island1314 &#x1f525;个人专栏&#xff1a;Linux—登神长阶 ⛺️ 欢迎关注&#xff1a;&#x1f44d;点赞 &#x1f442;&#x1f3fd;留言 &#x1f60d;收藏 &#x1f49e; &#x1f49e; &#x1f49e; 1. 线程安全和重入问题&…

数字电路期末复习

*前言&#xff1a;*写的东西不太全面&#xff0c;更多的是一个复习大纲&#xff0c;让你发现自己有哪些不懂的问题&#xff08;不懂的地方就去翻书或者问AI&#xff09;&#xff0c;如果能够解决提出的所有问题&#xff0c;那么过期末考一定不是问题。 这里写目录标题 数制和码…