Django之FBV与CBV
一、FBV与CBV
FBV(function based views),即基于函数的视图;CBV(class based views),即基于类的视图,也是基于对象的视图。当看到这个解释时,我是很萌的,我仔细回想了一下,哪里有基于类的视图啊,怎么我之前写的视图都是一个一个的函数啊,奇怪了,很多人都应该和我一样蒙(大佬除外哈)。没错我之前写的所有的视图都是基于函数的,所以今天咋们不去扯什么是FBV了,实在不知道的,可以看看在今天之前的所有视图,绝对都是FBV模型的(这个我敢打包票)。
二、CBV的实现代码
当听到基于class时,就会想到对象,瞬间有点慌,总感觉对象这个东西要比函数难,没有那么好理解,这应该是大多数人的共性,但在python中处处皆对象,你不想碰他就不能碰他?????不可能的,要想使你的代码更有水平,那你就避不开对象,而且对于开发来说,肯定都是要用到对象。其实哈这个基于对象的视图很好理解。
1,先写视图
from django.shortcuts import render,HttpResponse
from django.views import View
class myview(View):
def get(self,request):
return render(request,'login.html')
def post(self,request):
return HttpResponse('post请求')
2,写一个登录的页面
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>Title</title>
</head>
<body>
<form action="" method="post">
{% csrf_token %}
<label for="user">用户名:</label>
<input type="text" name="user" id="user">
<label for="pwd">密码:</label>
<input type="password" name="pwd" id="pwd">
<input type="submit" value="提交">
</form>
</body>
</html>
3,url
from django.contrib import admin
from django.urls import path
from app01 import views
urlpatterns = [
path('admin/', admin.site.urls),
path('login/', views.myview.as_view()),
]
4,分析过程
首先我们得看url,当请求路径是login时,会调用views里面的myview类的一个方法as_view,在这里我们先不管这个方法到底干了啥,只是说说执行流程。在浏览器地址栏输入login路径时,用的是get请求,它就会去调用myview类下的自己写的get,然后饭后一个登录页面;得到页面后输入用户名和密码之后点击提交按钮,又往login路径发送了一个post请求,这时就会调用myview类下的自己写的post方法,返回一个‘post请求’字符,这就是整个过程,从两个流程来看,大概可以猜出,整个过程中,django会判断请求的方式,不同的请求方式调用相应的方法
三、分析源码
既然在我自定义的myview类里没有写任何关于请求方式的逻辑,那我们应该猜测到,在myview继承的View类里面肯定有相关的东西(大佬经验,阅读源码时,看不懂就不要去看,不要去分析,只看我们需要的)。
1,源码
class View:
"""
Intentionally simple parent class for all views. Only implements
dispatch-by-method and simple sanity checking.
""" http_method_names = ['get', 'post', 'put', 'patch', 'delete', 'head', 'options', 'trace'] def __init__(self, **kwargs):
"""
Constructor. Called in the URLconf; can contain helpful extra
keyword arguments, and other things.
"""
# Go through keyword arguments, and either save their values to our
# instance, or raise an error.
for key, value in kwargs.items():
setattr(self, key, value) @classonlymethod
def as_view(cls, **initkwargs):
"""Main entry point for a request-response process."""
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 # take name and docstring from class
update_wrapper(view, cls, updated=()) # and possible attributes set by decorators
# like csrf_exempt from dispatch
update_wrapper(view, cls.dispatch, assigned=())
return view def dispatch(self, request, *args, **kwargs):
# Try to dispatch to the right method; if a method doesn't exist,
# defer to the error handler. Also defer to the error handler if the
# request method isn't on the approved list.
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) def http_method_not_allowed(self, request, *args, **kwargs):
logger.warning(
'Method Not Allowed (%s): %s', request.method, request.path,
extra={'status_code': 405, 'request': request}
)
return HttpResponseNotAllowed(self._allowed_methods()) def options(self, request, *args, **kwargs):
"""Handle responding to requests for the OPTIONS HTTP verb."""
response = HttpResponse()
response['Allow'] = ', '.join(self._allowed_methods())
response['Content-Length'] = ''
return response def _allowed_methods(self):
return [m.upper() for m in self.http_method_names if hasattr(self, m)]
2,剖析
在url里面,我们可以看到当请求过来后,执行的是views.myview.as_view(),所以我们去看看as_view()这个方法到底干了啥,首先在我们自定义的myview类里面没有这个方法,那就去父类View里找。
上面说过看不懂的就不要看,所以我把看不懂的给删除了
@classonlymethod
def as_view(cls, **initkwargs): #这是as_view方法 def view(request, *args, **kwargs): #这是as_view方法里嵌套一个方法view
self = cls(**initkwargs) #这是用myview类实例化的一个对象self
return self.dispatch(request, *args, **kwargs) #这是用实例化对象self去调用dispatch方法,然后作为view方法的返回值值
return view #这是返回view这个方法,也就是把view方法的返回值作为as_view的返回值,
接下来我们得去看看dispatch方法干了什么,首先也得从自定义的myview类里找dispatch方法,没找到,然后去父类View里找,
http_method_names = ['get', 'post', 'put', 'patch', 'delete', 'head', 'options', 'trace']
def dispatch(self, request, *args, **kwargs): #这是dispatch方法
if request.method.lower() in self.http_method_names: #这是把请求的方法取出来,然后小写,看有没有在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) #返回请求方式对应方法的执行结果
比如说是get请求进来后,它就利用反射会去myview里面拿到一个叫get的方法,在我的myview类下就有我自定义的get方法,然后执行它,得到一个HTTPResponse对象,返回给dispatch方法,dispatch方法又把这个HTTPResponse对选哪个返回给了view方法,
view方法又把这个对象返回给as_view方法,as_view方法又把这个作为响应返回给客户端,这整个过程简化中间的过程就会变成,get方法返回一个HTTPResponse对象给客户端
Django之FBV与CBV的更多相关文章
- django的FBV和CBV
title: python djano CBV FBV tags: python, djano, CBV, FBV grammar_cjkRuby: true --- python django的fu ...
- django的FBV和CBV的装饰器例子
备忘 def auth(func): def inner(request,*args,**kwargs): u = request.COOKIES.get('username111') if not ...
- Django之FBV和CBV的用法
FBV FBV,即 func base views,函数视图,在视图里使用函数处理请求. 以用户注册代码为例, 使用两个函数完成注册 初级注册代码 def register(request): &qu ...
- Django的FBV和CB
Django的FBV和CBV FBV FBV(function base views) 就是在视图里使用函数处理请求. 在之前django的学习中,我们一直使用的是这种方式,所以不再赘述. CBV C ...
- django请求生命周期,FBV和CBV,ORM拾遗,Git
一.django 请求生命周期 流程图: 1. 当用户在浏览器中输入url时,浏览器会生成请求头和请求体发给服务端请求头和请求体中会包含浏览器的动作(action),这个动作通常为get或者post, ...
- django——FBV与CBV
引言 FBV FBV(function base views) 就是在视图里使用函数处理请求. 在之前django的学习中,我们一直使用的是这种方式,所以不再赘述. CBV CBV(class bas ...
- python 全栈开发,Day84(django请求生命周期,FBV和CBV,ORM拾遗,Git)
一.django 请求生命周期 流程图: 1. 当用户在浏览器中输入url时,浏览器会生成请求头和请求体发给服务端请求头和请求体中会包含浏览器的动作(action),这个动作通常为get或者post, ...
- django基础 -- 4. 模板语言 过滤器 模板继承 FBV 和CBV 装饰器 组件
一.语法 两种特殊符号(语法): {{ }}和 {% %} 变量相关的用{{}},逻辑相关的用{%%}. 二.变量 1. 可直接用 {{ 变量名 }} (可调用字符串, 数字 ,列表,字典,对象等) ...
- django中的FBV和CBV
django中请求处理方式有2种:FBV 和 CBV 一.FBV FBV(function base views) 就是在视图里使用函数处理请求. 看代码: urls.py from django.c ...
随机推荐
- squid常用操作
如何查看squid的缓存命中率 使用命令: squidclient -h host -p port mgr:info比如: /usr/local/squid/bin/squidclient -h 12 ...
- 20175316盛茂淞 《java程序设计》第三周课堂测试错题总结
20175316盛茂淞 <java程序设计>第三周课堂测试错题总结 出现问题 错题总结 题目1 在Ubuntu中用自己的有位学号建一个文件,教材p87 Example4_15 1. 修改代 ...
- APP微信支付报错《商户号该产品权限未开通,请前往商户平台>产品中心检查后重试》
问题 最近项目使用MUI,HBuilder.开发打包H5的app 在开发H5 plus支付的时候,遇到以下问题: App微信支付调官方的统一下单接口返回错误信息 {return_msg=商户号该产品权 ...
- 把router-link标签渲染成指定的标签
<router-link>标签默认渲染成 <a>标签,可以通过tag属性把router-link渲染成指定的标签,如: <router-link to="/&q ...
- Localization
Localization (using Histogram Filters) 定位指的是在传感器和移动之间来回的迭代,使得能够保持跟踪目标对象的位置.方向和速度. 这篇将写一个程序来实施定位,与GPS ...
- Ngui使用随心记
Ngui的一些基础使用心得! BB:首先BB一下我觉得NGUI和UGUI哪个好?我首推UGUI,先不说是官方内置,在使用的方便性上也要好很多,而且NGUI停止更新了!还有就是NGUI有BUG! Ngu ...
- mybatis环境配置与入门例子
1.jar包的导入 mybatis需要jar包:mybatis-3.4.6.jar mysql驱动jar包:mysql-connector-java-5.1.34.-bin.jar 日志记录jar包: ...
- Java 获取当前项目所在服务器的 IP 地址
java中获取当前服务器地址主要使用到InetAddress这个类 public static void main(String[] args) { try { //用 getLocalHost() ...
- mysql之select语法
一:连接查询(外链接outer和内链接inner) 连接查询是另一种类型的多表查询.连接查询对多个表进行JOIN运算,简单地说,就是先确定一个主表作为结果集,然后,把其他表的行有选择性地“连接”在主表 ...
- javaweb目录结构简介
以上图说明: bbs目录代表一个web应用 bbs目录下的html,jsp文件可以直接被浏览器访问 WEB-INF目录下的资源是不能直接被浏览器访问的 web.xml文件是web程序的主要配置文件 所 ...