正在进入ing...

djangoCBV模式使用装饰器

发布时间:2020-09-08 浏览量: 1992 文章分类: python

这篇文章很早之前就想记录一下,避免忘记了,不过一直没机会,趁着这次机会。刚好重新梳理整理一下。

Django的基于函数视图(FBV)模式

FBV也是我们比较常用的,如果比较简短的小功能,一般我都是用这种模式来写的。FBV就是Function Base View的简写,我自己觉得常用的模式主要就是借助于模板,将数据渲染返回前端。 例:

from django.shortcuts import render

def index(request):
    return render(request,'index.html')

上面就是一个最简单的基于函数视图的实现方式。这种方式简单直观,各种数据也都会在request中,对于请求的类型也可以通过request.method进行各种判断。综合来说小项目就推荐这种模式。

Django基于类视图(CBV)模式

Class Base View这种模式我理解的主要是为了前后端分离而延伸出来的,不过确实很香,特别我这种不是很熟悉前端的,只要通过JSON方式和前端进行数据交互就可以了。 Django自带了CBV模式,当然也可以借用更加强大的第三方模块restful framework这个等以后有时间,我在整理一篇单独的文章。实例这里,我就用Django自带的

from django.views import View

class StudentView(View):
    def get(self,request):
        return JsonResponse({'method':'GET'})

    def post(self,request):
        return JsonResponse({'method':'POST'})

在上面就实现了最简单的一个CBV模式,这里需要详细说明一下首先需要引入django.views 的View然后我们的类需要继承ViewDjango是一个很强大的框架,他基于反射实现了不同的请求帮助我们跳转到不同的类方法。 在查看源码后,大致如下 + 1、首先View可以实现处理以下方式的http请求get,post, put, patch, delete, head, options, trace

  • 2、我们在配置url的方式也不能单独是引入直接使用了
    path('index/',views.index), #基于FBV模式
    path('stu/',views.StudentView.as_view()), #基于CBV模式

这里多了一个.as_view()方法,它就属于我们上面在view中引入的django.viewsView的方法。源码也比较简单,这里就不展开讲了,自己看代码吧

    @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))
  • 3、在view方法中,有一个self.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)

现在说完了CBV、FBV的处理逻辑。我们已经大致知道他们的请求经过的顺序了。那也回归到正题上,结论如下 1、FBV是从路由系统直接跳转到视图函数中的,所以可以直接使用装饰器; 2、CBV因为涉及到类继承等一大堆判断,因此装饰器套上要么无效,要么报错。

这里我拿一个Django自带的csrf验证的装饰器来示范。 在FBV模式下就比较简单。

from django.views.decorators.csrf import csrf_exempt

@csrf_exempt
def index(request):
    return render(request,'index.html')

而在CBV模式下,直接给getpost方法套用的方式很明显就不对了。因为,如果要使用的话,需要调用一下父类(View)的dispatch方法。

from django.utils.decorators import method_decorator

class StudentView(View):
    @method_decorator(csrf_exempt)
    def dispatch(self, request, *args, **kwargs):
        return super(StudentView, self).dispatch(request, *args, **kwargs)

    def get(self,request):
        return JsonResponse({'method':'GET'})

    def post(self,request):
        return JsonResponse({'method':'POST'})

这样就可以在类视图中使用装饰器了。