django类视图简单使用和源码解析
django的类视图,CBV:
我们在开始接触django的时候,习惯于使用函数编写视图,即FBV。使用FBV时,我们只需要在路由匹配时,对应的路由下找到这个函数就可以了,这样做看似很和谐,但是有的时候,譬如说,当我们需要根据同一个url请求方法的不同而去执行不同的操作时,如果使用FBV去编写视图,那么我们就需要在视图函数中不断地去执行if request.method=='请求方法' 去判断要去执行什么内容,此时的代码就显得不是很优雅。但是此时如果我们使用CBV的方式来编写视图,同样的需求,代码就会显得优雅很多,下面就让我来介绍一下CBV的具体实现:
在django中使用CBV编写视图:
1、首先我们自定义的视图类需要继承django.views.View类
2、在视图类中定义以'请求方法名称小'写为名称的方法,这样在执行不同的请求方法的时候就回去自动执行对应的函数
3、在路由映射的时候,要执行这个试图类的as_view()方法,注意这个方法继承自django.views.View
示例代码如下:
'views.py'文件:
from django.views import View
from django.http import HttpResponse
class UserInfoView(View):
def get(self, request, *args, **kwargs):
return HttpResponse('get user')
def post(self, request, *args, **kwargs):
return HttpResponse('post user')
def delete(self, request, *args, **kwargs):
return HttpResponse('delete user')
'url.py'文件
from app import views
urlpatterns = [
path('user/', views.UserInfoView.as_view())
]
上述示例代码就可以根据同一个url执行不同的方法时去执行不同的操作
CBV实现的源码分析:
1、请求进来,路由找到试图类并执行as_view方法,执行这个方法时其实会返回一个view函数,因此可以看做请求进来之后会先执行试图类的view方法,源码如下:
@classonlymethod
def as_view(cls, **initkwargs):
for key in initkwargs:
if key in cls.http_method_names:
raise TypeError("You tried to pass in the %s method name as a "
"keyword argument to %s(). Don't do that."
% (key, cls.__name__))
if not hasattr(cls, key):
raise TypeError("%s() received an invalid keyword %r. as_view "
"only accepts arguments that are already "
"attributes of the class." % (cls.__name__, key))
def view(request, *args, **kwargs):
self = cls(**initkwargs)
if hasattr(self, 'get') and not hasattr(self, 'head'):
self.head = self.get
self.request = request
self.args = args
self.kwargs = kwargs
return self.dispatch(request, *args, **kwargs)
view.view_class = cls
view.view_initkwargs = initkwargs
update_wrapper(view, cls, updated=())
update_wrapper(view, cls.dispatch, assigned=())
return view
2、从上面的源码中可以看出执行view方法,实际上就是返回self.dispatch方法,也就是说会去执行self.dispatch方法
3、因为试图类本身没有定义dispatch方法,那么在执行dispatch方法的时候就需要去其父类里面查找,而父类里面的dispatch方法则会根据请求方法的不同基于python类的反射去找到相应的方法,然后执行,这样就会自动实现根据请求方法的不同去执行不同的内容了,dispatch方法的源码如下:
def dispatch(self, request, *args, **kwargs):
if request.method.lower() in self.http_method_names:
handler = getattr(self, request.method.lower(), self.http_method_not_allowed)
else:
handler = self.http_method_not_allowed
return handler(request, *args, **kwargs)
CBV之添加装饰器:
在我们使用函数试图FBV的时候,如果我们想要给其加上一个装饰器,直接加就可以了,例如,在创建django项目的时候,默认全局使用csrf防护,如果我们想要在某个函数试图上不使用CSRF保护,那么我们可以给这个视图函数直接添加一个装饰器即可,示例代码如下:
from django.views.decorators.csrf import csrf_exempt @csrf_exempt
def index(request):
return HttpResponse('index')
但是,当我们想要给CBV添加装饰器,那么我们需要做的就不是在其内部的方法上添加,如果和FBV一样直接添加到方法上,那么这不会起任何作用。在CBV上添加装饰器的方法有两种,第一种是重写父类的dispatch方法,并将装饰器添加到dispatch方法上,与此同时在CBV上添加装饰器最好使用django.utils.decorators.method_decorator方法进行包裹。第二种方法则是直接添加在类上,只不过这时你需要使用django.utils.decorators.method_decorator来进行封装。下面的例子是我们在django中针对重要的数据操作,想要实现数据库的事件特性而添加的装饰器:
1、方法一:
from django.utils.decorators import method_decorator
from django.db import transaction class OrderView(View):
@method_decorator(transaction.atomic)
def dispatch(self, request, *args, **kwargs):
return super(OrderView, self).dispatch(request, *args, **kwargs) def get(self, request, *args, **kwargs):
pass def post(self, request, *args, **kwargs):
pass def patch(self, request, *args, **kwargs):
pass def delete(self, request, *args, **kwargs):
pass 2、方法二:
from django.utils.decorators import method_decorator
from django.db import transaction @method_decorator(transaction.atomic, name='dispatch')
class OrderView(View):
def get(self, request, *args, **kwargs):
pass def post(self, request, *args, **kwargs):
pass def patch(self, request, *args, **kwargs):
pass def delete(self, request, *args, **kwargs):
pass
django类视图简单使用和源码解析的更多相关文章
- Appium自动化(11) - 详解 Applications 类里的方法和源码解析
如果你还想从头学起Appium,可以看看这个系列的文章哦! https://www.cnblogs.com/poloyy/category/1693896.html 前言 Applications 类 ...
- rest-framework之视图和源码解析
视图和源码解析 通过使用mixin类编写视图: from rest_framework import mixins from rest_framework import generics class ...
- Dubbo原理和源码解析之服务引用
一.框架设计 在官方<Dubbo 开发指南>框架设计部分,给出了引用服务时序图: 另外,在官方<Dubbo 用户指南>集群容错部分,给出了服务引用的各功能组件关系图: 本文将根 ...
- Dubbo原理和源码解析之“微内核+插件”机制
github新增仓库 "dubbo-read"(点此查看),集合所有<Dubbo原理和源码解析>系列文章,后续将继续补充该系列,同时将针对Dubbo所做的功能扩展也进行 ...
- Spring源码解析02:Spring IOC容器之XmlBeanFactory启动流程分析和源码解析
一. 前言 Spring容器主要分为两类BeanFactory和ApplicationContext,后者是基于前者的功能扩展,也就是一个基础容器和一个高级容器的区别.本篇就以BeanFactory基 ...
- Spring源码解析 | 第二篇:Spring IOC容器之XmlBeanFactory启动流程分析和源码解析
一. 前言 Spring容器主要分为两类BeanFactory和ApplicationContext,后者是基于前者的功能扩展,也就是一个基础容器和一个高级容器的区别.本篇就以BeanFactory基 ...
- Go语言备忘录:net/http包的使用模式和源码解析
本文是晚辈对net/http包的一点浅显的理解,文中如有错误的地方请前辈们指出,以免误导! 转摘本文也请注明出处:Go语言备忘录:net/http包的使用模式和源码解析,多谢! 目录: 一.http ...
- Dubbo原理和源码解析之标签解析
一.Dubbo 配置方式 Dubbo 支持多种配置方式: XML 配置:基于 Spring 的 Schema 和 XML 扩展机制实现 属性配置:加载 classpath 根目录下的 dubbo.pr ...
- Go语言备忘录(3):net/http包的使用模式和源码解析
本文是晚辈对net/http包的一点浅显的理解,文中如有错误的地方请前辈们指出,以免误导! 转摘本文也请注明出处:Go语言备忘录(3):net/http包的使用模式和源码解析,多谢! 目录: 一.h ...
随机推荐
- vue和react总结
一.总结一下Vue和React的区别 相同点: 1.都支持服务器端渲染 2.都有Virtual DOM,组件化开发,通过props参数进行父子组件数据的传递,都实现webComponent ...
- 【赛事总结】◇赛时·8◇ AGC-027
[赛时·8]AGC-027 日常AGC坑……还好能涨Rating +传送门+ ◇ 简单总结 感觉像打多校赛一样,应该多关注一下排名……考试的时候为了避免影响心态,管都没有管排名,就在那里死坑B题.最后 ...
- Java语言利用Collections.sort对Map,List排序
1.main方法包含TreeMap排序1,TreeMap排序2,HashMap排序,List<Integer>排序,List<Bean>排序,List<Map>排序 ...
- PHP无法用下标访问
php数组分为普通数组和关联数组,普通数组可以用下标访问,而关联数组不可以.
- vue渲染自定义json数据
<template> <div class="wrap"> <div class="main"> <div class ...
- CacheManager源码分析
计算rdd的某个分区是从RDD的iterator()方法开始的,我们从这个方法进入 然后我们进入getOrCompute()方法中看看是如何进行读取数据或计算的 getOrElseUpdate()方方 ...
- mysql5.7数据库与5.7之前版本比较
数据库初始化方式变更 <5.7 版本 mysql_install_db >5.7 版本 bin/mysqld --initialize --user =mysql --basedir=/u ...
- py3.7.1下pyinstaller 的安装及打包 坑
实在无语了,写了个小程序,用pyinstaller打包,运行就出现这个pip install pywin32-ctypes.明明全部都已经安装了啊. 解决办法: 不要在工程设置里安装pyinstall ...
- python中的字符串(str)操作
字符串是python中数据类型.一般就单引号(‘’)或双引号(“”)引起来的内容就是字符串. 例如:下面两个都是定义字符串 str1 = "hello world" str2 = ...
- Go web表单
package main import ( "fmt" "html/template" "log" "net/http" ...