djangoCBV模式使用装饰器
这篇文章很早之前就想记录一下,避免忘记了,不过一直没机会,趁着这次机会。刚好重新梳理整理一下。
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然后我们的类需要继承View,Django是一个很强大的框架,他基于反射实现了不同的请求帮助我们跳转到不同的类方法。
在查看源码后,大致如下
+ 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.views中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))
- 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模式下,直接给get、post方法套用的方式很明显就不对了。因为,如果要使用的话,需要调用一下父类(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'})
这样就可以在类视图中使用装饰器了。