Django REST Framework剖析

1、简介

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

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

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

2、Django 的 CBV&FBV

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

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

注意:restful

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

3、Django CBV之CSRF

1.csrf校验:架构

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

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

 4、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

相关文章
相关标签/搜索