FBV与CBV

  FBV:function based view   基于函数的视图

  CBV:class based view  基于类的视图

  

  CBV的定义:

    from django.views import View

    class Cbv(View):

      def get(self,request):

        # 专门处理get请求的函数

      def post(self,request):

        # 专门处理post请求的函数

  CBV的路由配置:

    path('cbv_test',Cbv.as_view())

    as_view()的返回结果是一个处理好的FBV

  

  CBV和FBV:

    CBV能够直接根据请求方式直接匹配到对应的方法执行,FBV则需要在视图函数内部,通过request.method来判断请求方式,以便做不同的逻辑处理。

    不同的是,如果CBV中没有定义对应请求方式的处理方法的话,会报错。而FBV中没有对应请求方式的处理逻辑的话也不会有太大问题。

  

  as_view()源码:  

  @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.setup(request, *args, **kwargs)
  if not hasattr(self, 'request'):
   raise AttributeError(
   "%s instance has no 'request' attribute. Did you override "
  "setup() and forget to call super()?" % cls.__name__
  )
  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

  as_view是定义在View类里的类方法,CBV继承了View类,所以也就有了as_view方法。

  从源码上看,CBV调用了as_view方法,最后还是会返回一个函数地址,也就不违反路由配置中对于第二个参数要是一个函数地址的限制。

  所以,主要看as_view内部的view函数:

    request:wsgi封装好的请求对象,和FBV里拿到的request一模一样

    cls:表示当前调用该函数的类,也就是自定义的CBV

    self:就是由CBV实例化的对象

    然后将request赋值给当前CBV实例化的对象,所以CBV内部self.request和某个请求方法的request参数是同一个request。

    setup方法内部实现方式如下

    def setup(self, request, *args, **kwargs):
     """Initialize attributes shared by all view methods."""
    self.request = request
    self.args = args
    self.kwargs = kwargs

    最终返回View类中的dispatch方法的结果,作为返回值。

    接着看dispatch方法内部做了些什么:    

    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)

    首先获取当前请求的结果(字符串)并将其小写后,判断其是否在http_method_names列表中,也就意味着判断该请求方式在当前配置下是否允许。

    http_method_names = ['get', 'post', 'put', 'patch', 'delete', 'head', 'options', 'trace']

    该列表定义在View类内部的最上方,也就是说如果自定义某个CBV,想配置哪些请求方式是允许的,只要在CBV内部重写该列表即可。

    在当前请求方式是允许的情况,通过反射机制获取当前请求方式在CBV中对于的处理方法,如果获取不到对应的处理方法(即在CBV中没有定义,或者定义方法名不符合规范,因为它通过反射机制是要拿到方法名是小写的方法),则表明该方法无效。那么当前请求将会得到405错误页面,也就是先前说的,CBV必须要定义在许可范围内的请求处理方法,否则会出错。

    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())

    如果通过反射机制得到了相应请求的处理方法,则在调用该方法后,将该方法的结果作为返回值返回。也就是将相应请求的处理方法的response对象返回。

    也就是说CBV内部处理请求的方法,正在被执行的地方就在View类中的dispatch方法内。

    如果想要在处理请求的方法的执行前后,增加一些操作,可以在CBV内部重写 dispatch然后在调用父类的dispatch前后增加想要做的操作,如函数执行计时等。

  给CBV加装饰器

    需要先导入method_decorator

    from django.utils.decorators import method_decorator

    1、然后在CBV内部对应方法上加装饰器  @method_decorator(对应的装饰器地址)

    2、如果只想给单个请求方式对应的处理方法加上装饰器的话,直接就在对应方法上加即可

       如果想让所有请求方式对应的处理方法都加上装饰器的话,可以在CBV内部重写View类的dispatch方法,然后super调用View类的dispatch,最后把装饰器加在重写后的dispatch方法上。

    3、直接将装饰器加在CBV上@method_decorator(对应的装饰器地址,name='对应的方法名')

       或者@method_decorator(对应的装饰器地址,name='dispatch')

request对象

  request.method:获取当前的请求方式

  request.GET:获取URL上携带的参数

  request.POST:获取post请求提交的数据

  request.path_info:获取url的路径(不包括域名和携带的参数)

  request.get_full_path():获取url的路径(包括携带的参数)

  request.body:获取请求体中的数据,得到的结果为bytes类型

  request.scheme:返回请求协议(http/https)

  request.encoding:获取提交数据的编码方式,若为None则默认使用utf-8

  request.COOKIES:cookie字典,键值均为字符串

  request.session:session信息

  request.FILES:获取上传的文件

  request.META:返回一个字典,里面包含请求头的信息

  request.user:一个AUTH_USER_MODEL类型对象,表示当前登录的用户

  request.get_host():返回请求的原始主机,若主机位于多个代理后,get_host()将失效

  request.is_secure():判断请求是否安全(即是否是https发起的),返回布尔值

  request.is_ajax():判断请求是否是ajax发起的

Response对象

  HttpResponse("字符串")

  render(request, "模板", {数据字典})

  render_to_string("模板", {数据字典})   返回渲染后的模板文件的字符串

  redirect("地址")  重定向

  JsonResponse()返回json格式的响应,默认只能序列化字典 序列化其他需要加safe参数

  

  render方法中,调用了render_to_string将渲染后的模板文件的字符串,通过HttpResponse("字符串")返回给浏览器

    def render(request, template_name, context=None, content_type=None, status=None, using=None):
    """
    Return a HttpResponse whose content is filled with the result of calling
    django.template.loader.render_to_string() with the passed arguments.
    """
    content = loader.render_to_string(template_name, context, request, using=using)
    return HttpResponse(content, content_type, status)

  redirect("地址")本质就是将响应头中的Location值set为重定向的地址,并将状态码设置为301或者302返回给浏览器。

  以下代码同样能实现redirect方法的功能:

    ret = HttpResponse('', status = 301)

    ret['Location'] = '地址'

    return ret

  补充:临时重定向(响应状态码:302)和永久重定向(响应状态码:301)

  

    

    

django—视图相关的更多相关文章

  1. Django框架03 /视图相关

    Django框架03 /视图相关 目录 Django框架03 /视图相关 1. 请求相关 2.响应相关 3.FBV和CBV 视图(视图函数和视图类) 3.1 类视图 CBV 3.2 视图函数 FBV ...

  2. Django 视图系统

    Django 视图系统 概念 一个视图函数,简称视图,是一个简单的Python函数,用于接受Web请求并返回Web响应. 通常将视图函数写在project或app目录中的名为views.py文件中 简 ...

  3. Django 模板相关

    Django 模板相关 视图函数只是直接返回文本,而在实际生产环境中其实很少这样用,因为实际的页面大多是带有样式的HTML代码,这可以让浏览器渲染出非常漂亮的页面.目前市面上有非常多的模板系统,其中最 ...

  4. Django视图层之路由配置系统(urls)

    视图层之路由配置系统(urls) URL配置(URLconf)就像Django 所支撑网站的目录.它的本质是URL与要为该URL调用的视图函数之间的映射表:你就是以这种方式告诉Django,对于这个U ...

  5. 1.2、Django 视图与网址__进阶

    Django 视图与网址进阶 1.1.简单使用: 把我们新定义的app加到settings.py中的INSTALL_APPS中 修改 HelloDjango/HelloDjango/settings. ...

  6. [diango]理解django视图工作原理

    前言:正确理解django视图view,模型model,模板的概念及其之间的关联关系,才能快速学习并上手使用django制作网页 本文主要讲解自己在学习django后对视图view的理解 在进入正文之 ...

  7. Django 2.0 学习(03):Django视图和URL(下)

    接上篇博文,继续分析Django基本流程. 编写第一个(view)视图函数 1.打开文件polls/views.py,输入下面的Python代码: from django.http import Ht ...

  8. 如何在django视图中使用asyncio(协程)和ThreadPoolExecutor(多线程)

    Django视图函数执行,不在主线程中,直接 loop = asyncio.new_event_loop() # 更不能loop = asyncio.get_event_loop() 会触发 Runt ...

  9. 令Django 视图有默认 login_required

    方法一 from django.template import RequestContext from django.shortcuts import render_to_response from ...

随机推荐

  1. 【python】列表与数组之间的相互转换

    安装numpy pip3 install numpy 列表转数组 np.array() import numpy as np a = [1, 2, 3] b = np.array(a) 列表转数组 a ...

  2. CSS、bootstrap4等相关疑难杂症

    说明 本篇博客仅用于个人随笔,所以内容比较随意. 在bootstrap4中,引入样式后,按钮.输入框等组件的选取状态会出现黑色加重边框,该如何解决? 解决示例: input:focus{outline ...

  3. 条件编译(debug)

    1. #ifdef 标识符 代码段1 #else 代码段2(可以为空) #endif (条件编译结束语句,和#ifdef配套使用) 如果标识符被#define过,则编译代码段1,否则编译代码段2 2. ...

  4. Linux基本目录机构

    Linux基本目录机构 1. 基本介绍 Linux的文件系统采用级层式子的树状目录结构 最上层是根目录"/" Linux世界里,一切皆文件 2. 目录用途 /bin: 是Binar ...

  5. PHP绕过disable_function

    PHP绕过disable_function 常规绕过 exec exec执行command命令,但是不会输出全部结果,而是返回结果的最后一行. 想得到全部的结果,可以使用第二个参数,让其输出到一个数组 ...

  6. AI小白必读:深度学习、迁移学习、强化学习别再傻傻分不清

    摘要:诸多关于人工智能的流行词汇萦绕在我们耳边,比如深度学习 (Deep Learning).强化学习 (Reinforcement Learning).迁移学习 (Transfer Learning ...

  7. React代码开发规范

    前言 一般在团队开发中每个人的代码习惯都不太一样,这样就会导致代码风格不一致,以致于维护和修改bug的时候看别人的代码成为一种痛苦...这种情况尤其在前端开发中尤为明显.因为关于前端的开发规范貌似也没 ...

  8. idea模拟前端向后台请求数据输出响应结果

    tools-httpClient-Test restful web service 通过上述步骤之后出现如下图 1 表示通过哪种方式请求:2 请求数据的地址头部:3 请求数据的除了头部之后的地址:4, ...

  9. Java泛型中的类型参数和通配符类型

    类型参数 泛型有三种实现方式,分别是泛型接口.泛型类.泛型方法,下面通过泛型方法来介绍什么是类型参数. 泛型方法声明方式:访问修饰符 <T,K,S...> 返回类型 方法名(方法参数){方 ...

  10. tensorflow(一):基础

    一.张量 1.张量的概念 在TensorFlow中,所有的数据都通过张量的形式来表示.从功能的角度,张量可以简单理解为多维数组,零阶张量表示标量(scalar),也就是一个数:一阶张量为向量(vect ...