一、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的更多相关文章

  1. django的FBV和CBV

    title: python djano CBV FBV tags: python, djano, CBV, FBV grammar_cjkRuby: true --- python django的fu ...

  2. django的FBV和CBV的装饰器例子

    备忘 def auth(func): def inner(request,*args,**kwargs): u = request.COOKIES.get('username111') if not ...

  3. Django之FBV和CBV的用法

    FBV FBV,即 func base views,函数视图,在视图里使用函数处理请求. 以用户注册代码为例, 使用两个函数完成注册 初级注册代码 def register(request): &qu ...

  4. Django的FBV和CB

    Django的FBV和CBV FBV FBV(function base views) 就是在视图里使用函数处理请求. 在之前django的学习中,我们一直使用的是这种方式,所以不再赘述. CBV C ...

  5. django请求生命周期,FBV和CBV,ORM拾遗,Git

    一.django 请求生命周期 流程图: 1. 当用户在浏览器中输入url时,浏览器会生成请求头和请求体发给服务端请求头和请求体中会包含浏览器的动作(action),这个动作通常为get或者post, ...

  6. django——FBV与CBV

    引言 FBV FBV(function base views) 就是在视图里使用函数处理请求. 在之前django的学习中,我们一直使用的是这种方式,所以不再赘述. CBV CBV(class bas ...

  7. python 全栈开发,Day84(django请求生命周期,FBV和CBV,ORM拾遗,Git)

    一.django 请求生命周期 流程图: 1. 当用户在浏览器中输入url时,浏览器会生成请求头和请求体发给服务端请求头和请求体中会包含浏览器的动作(action),这个动作通常为get或者post, ...

  8. django基础 -- 4. 模板语言 过滤器 模板继承 FBV 和CBV 装饰器 组件

    一.语法 两种特殊符号(语法): {{ }}和 {% %} 变量相关的用{{}},逻辑相关的用{%%}. 二.变量 1. 可直接用  {{ 变量名 }} (可调用字符串, 数字 ,列表,字典,对象等) ...

  9. django中的FBV和CBV

    django中请求处理方式有2种:FBV 和 CBV 一.FBV FBV(function base views) 就是在视图里使用函数处理请求. 看代码: urls.py from django.c ...

随机推荐

  1. eclipse启动时出现无法创建java虚拟机

    最 近一直在用eclipse开发android程序,今天不知怎么的启动eclipse时就会出现Failed to create java virtual machine,无法打开eclipse程序,折 ...

  2. JS基础-运算符-函数

    1.运算符  1.赋值运算符和扩展运算符    1.赋值运算符 =    2.扩展运算符      +=,-=,*=,/=,%=,^=....      ex:        a=a+b;--> ...

  3. 小白的CTF学习之路1——程序与CPU

    刚刚注册了这个博客园,尽量保持每日一更(*/ω\*) 今天看了po学院的教学视频,了解了程序是什么,如何在CPU当中工作的等各种之前未曾想过的问题,特此记录,以防忘记 首先我们学习程序与CPU之前需要 ...

  4. hdu-1878(欧拉回路)

    题目链接:传送门 思路:就是判断无向图的欧拉回路的两个条件:(1)连通性(2)点的度数是偶数 注意:两个条件一同时满足才行. #include<iostream> #include< ...

  5. drf3 Serializers 序列化组件

    为什么要用序列化组件 做前后端分离的项目,我们前后端交互一般都选择JSON数据格式,JSON是一个轻量级的数据交互格式. 给前端数据的时候都要转成json格式,那就需要对从数据库拿到的数据进行序列化. ...

  6. slecte下拉框的多选操作及获取值的 变化

    对select增加一个 multiple属性,再获取多选的值的时候,对数据进行遍历,如果单纯的获取select的value值,指挥获取一个值, 遍历方法 可以先获取到select的dom元素到,然后对 ...

  7. c++ 日志输出库 spdlog 简介(2)

    继续上一篇,example.cpp解析. 1.set_pattern 自定义日志格式 官方参考:https://github.com/gabime/spdlog/wiki/3.-Custom-form ...

  8. Request模块—数据解析工具

    一.爬虫基本步骤 指定URL信息 发起请求 获取响应数据 对响应数据进行数据解析 持久化存储 二.数据解析 1. 正则表达式 (1) 基本语法 1. 单字符: . : 除换行以外所有字符 [] :[a ...

  9. maya2018卸载/安装失败/如何彻底卸载清除干净maya2018注册表和文件的方法

    maya2018提示安装未完成,某些产品无法安装该怎样解决呢?一些朋友在win7或者win10系统下安装maya2018失败提示maya2018安装未完成,某些产品无法安装,也有时候想重新安装maya ...

  10. JS应用实例6:二级联动

    本案例很常用,应用场景:注册页面填写籍贯,省市二级联动 总体思想:创建一个二维数组存入省市,获取选中的省份并比较,创建标签遍历添加 代码: <!DOCTYPE html> <html ...