# 简单实例
from django.views import View
class Books(View):
def get(self,request, *args, **kwargs):
print("get")
return HttpResponse("ok")
def dispatch(self, request, *args, **kwargs):
print("dispatch")
ret = super(Books,self).dispatch(request, *args, **kwargs)
print("ret",ret)
return HttpResponse(ret)
# 通过url(r"books/$",views.BookView.as_view())入手
@classmethod
def as_view(cls, **initkwargs):
"""
Store the original class on the view function.
This allows us to discover information about the view when we do URL
reverse lookups. Used for breadcrumb generation.
"""
if isinstance(getattr(cls, 'queryset', None), models.query.QuerySet):
def force_evaluation():
raise RuntimeError(
'Do not evaluate the `.queryset` attribute directly, '
'as the result will be cached and reused between requests. '
'Use `.all()` or call `.get_queryset()` instead.'
)
cls.queryset._fetch_all = force_evaluation
view = super(APIView, cls).as_view(**initkwargs)
view.cls = cls
view.initkwargs = initkwargs
# Note: session based authentication is explicitly CSRF validated,
# all other authentication is CSRF exempt.
return csrf_exempt(view)
APIView
类是继承View
类,view
类是from django.views import View
下的View
在APIView
类中,我们重点了解return csrf_exempt(view)
def csrf_exempt(view_func):
"""
Marks a view function as being exempt from the CSRF view protection.
"""
# We could just do view_func.csrf_exempt = True, but decorators
# are nicer if they don't have side-effects, so we return a new
# function.
def wrapped_view(*args, **kwargs):
return view_func(*args, **kwargs)
wrapped_view.csrf_exempt = True
return wraps(view_func, assigned=available_attrs(view_func))(wrapped_view)
wrapped_view.csrf_exempt = True
意思是取消当前函数防跨站请求伪造功能,即便settings中设置了全局中间件
然后将csrf_exempt
函数中的内置函数wrapped_view
赋值wrapped_view.csrf_exempt = True
,使其拥有该属性,
# wraps函数
def wraps(wrapped,
assigned = WRAPPER_ASSIGNMENTS,
updated = WRAPPER_UPDATES):
return partial(update_wrapper, wrapped=wrapped,
assigned=assigned, updated=updated)
wrapped是在def csrf_exempt(view_func):
函数中的参数,也就是as_view
的返回值
然后通过functools
模块下的partial
类进行装饰构造,partial 这个东西是针对函数起作用的,并且是部分的
# partial函数
def __new__(*args, **keywords):
if not args:
raise TypeError("descriptor '__new__' of partial needs an argument")
if len(args) < 2:
raise TypeError("type 'partial' takes at least one argument")
cls, func, *args = args
if not callable(func):
raise TypeError("the first argument must be callable")
args = tuple(args)
if hasattr(func, "func"):
args = func.args + args
tmpkw = func.keywords.copy()
tmpkw.update(keywords)
keywords = tmpkw
del tmpkw
func = func.func
self = super(partial, cls).__new__(cls)
self.func = func
self.args = args
self.keywords = keywords
return self
def __call__(*args, **keywords):
if not args:
raise TypeError("descriptor '__call__' of partial needs an argument")
self, *args = args
newkeywords = self.keywords.copy()
newkeywords.update(keywords)
return self.func(*self.args, *args, **newkeywords)
在csrf_exempt
函数中的wraps(view_func, assigned=available_attrs(view_func))(wrapped_view)
传入参数wrapper view
, 通过对象可调用功能,进行调用__call__
方法 .
原文:https://www.cnblogs.com/kp1995/p/10596569.html