• Django REST Framework剖析


    一、简介

    Django REST Framework(简称DRF),是一个用于构建Web API的强大且灵活的工具包。

    先说说REST:REST是一种Web API设计标准,是目前比较成熟的一套互联网应用程序的API设计理论。

    Fielding将他对互联网软件的架构原则,定名为REST,即Representational State Transfer的缩写。我对这个词组的翻译是”表现层状态转化”。如果一个架构符合REST原则,就称它为RESTful架构。所以简单来说,RESTful是一种Web API设计规范,根据产品需求需要定出一份方便前后端的规范,因此不是所有的标准要求都需要遵循。

    二、Django 的 CBV&FBV

    Django FBV, function base view  视图里使用函数处理请求

    url(r‘^users/‘, views.users),
    
    from django.shortcuts import HttpResponse
    import json
    def users(request):
        user_list = ['lcg','superman']
        return HttpResponse(json.dumps((user_list)))
    

    Django CBV, class base view 视图里使用类处理请求

    路由:
      url(r'^students/', views.StudentsView.as_view()),
    			
    视图:
    from django.shortcuts import HttpResponse
    from django.views import View
    class StudentsView(View):
    
    	def get(self,request,*args,**kwargs):
    		return HttpResponse('GET')
    
    	def post(self, request, *args, **kwargs):
    		return HttpResponse('POST')
    
    	def put(self, request, *args, **kwargs):
    		return HttpResponse('PUT')
    
    	def delete(self, request, *args, **kwargs):
    		return HttpResponse('DELETE')
    

    注意:

    • cbv定义类的时候必须要继承view
    • 在写url的时候必须要加as_view
    • 类里面使用form表单提交的话只有get和post方法
    • 类里面使用ajax发送数据的话支持定义以下很多方法
      restful规范:
      'get'获取数据, 'post'创建新数据, 'put'更新, 'patch'局部更新, 'delete'删除, 'head', 'options', 'trace'

    三、Django CBV之CSRF

    1.csrf校验:

    基于中间件的process_view方法实现对请求的csrf_token验证

    2.不需要csrf验证方法:

    fbv:

    from django.views.decorators.csrf import csrf_exempt
    
    @csrf_exempt
    def index(request):
        pass
    

     cbv:

    方式一

    ###方式一
    from django.shortcuts import render,HttpResponse
    from django.views.decorators.csrf import csrf_exempt,csrf_protect
    from django.utils.decorators import method_decorator
    from django.views import View
    
    class Myview(View):
        @method_decorator(csrf_exempt)    #必须将装饰器写在dispatch上,单独加不生效
        def dispatch(self, request, *args, **kwargs):
            return super(Myview,self).dispatch(request,*args,**kwargs)
    
        def get(self):
            return HttpResponse('get')
    
        def post(self):
            return HttpResponse('post')
    
        def put(self):
            return HttpResponse('put')
    

     方式二:

    from django.shortcuts import render,HttpResponse
    from django.views.decorators.csrf import csrf_exempt,csrf_protect
    from django.utils.decorators import method_decorator
    from django.views import View
    
    @method_decorator(csrf_exempt,name='dispatch')##name参数指定是dispatch方法
    class Myview(View):
    
        def dispatch(self, request, *args, **kwargs):
            return super(Myview,self).dispatch(request,*args,**kwargs)
    
        def get(self):
            return HttpResponse('get')
    
        def post(self):
            return HttpResponse('post')
    
        def put(self):
            return HttpResponse('put')
    

     四、CBV原理:继承,反射

    请求到达Django会先执行Django中间件里的方法,然后进行进行路由匹配。在路由匹配完成后,会执行CBV类中的as_view方法。
    CBV中并没有定义as_view方法,由于CBV继承自Django的View,所以会执行Django的View类中的as_view方法
    Django的View类的源码:

    class View(object):
        """
        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 six.iteritems(kwargs):
                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 http.HttpResponseNotAllowed(self._allowed_methods())
     
        def options(self, request, *args, **kwargs):
            """
            Handles responding to requests for the OPTIONS HTTP verb.
            """
            response = http.HttpResponse()
            response['Allow'] = ', '.join(self._allowed_methods())
            response['Content-Length'] = '0'
            return response
     
        def _allowed_methods(self):
            return [m.upper() for m in self.http_method_names if hasattr(self, m)]
    

    上面实质上是路由里面的那里写的as_view ,返回值是view 而view方法返回的是self.dispath

    在dispatch方法中,把request.method转换为小写再判断是否在定义的http_method_names中,如果request.method存在于http_method_names中,则使用getattr反射的方式来得到handler

    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)
    

     在这里的dispatch方法中,self指的是自定义的CBV类实例化得到的对象,从CBV类中获取request.method对应的方法,再执行CBV中的方法并返回
    由此,可以知道如果在Django项目中使用CBV的模式,实际上调用了getattr的方式来执行获取类中的请求方法对应的函数

     也就是说,继承自View的类下的所有的方法本质上都是通过dispatch这个函数反射执行,如果想要在执行get或post方法前执行其他步骤,可以重写dispatch

  • 相关阅读:
    String StringBuffer StringBuilder 之间的区别
    StringBuffer和String的相互转换
    StringBuffer的替换和反转和截取功能
    StringBuffer的添加与删除功能
    后端——框架——容器框架——spring_core——容器
    后端——框架——容器框架——spring_core——bean以及xml配置
    后端——框架——容器框架——spring_core——注解
    后端——框架——容器框架——spring_core——国际化 & Properties
    后端——框架——容器框架——spring_core——Resource
    后端——框架——容器框架——spring_core——校验器
  • 原文地址:https://www.cnblogs.com/honey-badger/p/9728788.html
Copyright © 2020-2023  润新知