CBV使用

原理流程

CBV是基于反射实现根据请求方法的不同,以此来执行不同的方法(getattr()方法)

getattr可以直接获取对象属性,返回值可以直接使用
class A(object):

...class A:     
            def set(self, a, b):
...         x = a
...         a = b
...         b = x
...         print a, b
...
a = A()
c = getattr(a, 'set')
c(a='1', b='2')
2 1

对应不同的get,post,put,delete请求来实现执行不同方法的原理
url .as_view() -> view 方法 -> dispatch()方法 (反射执行:GET/POST/DELETE/PUT)
image.png

http_method_names = ['get', 'post', 'put', 'patch', 'delete', 'head', 'options', 'trace']

如果request的方法在http_method_name这个列表列出的方法内,那么就通过getattr得到这个对象的属性,然后执行。

源码

class MyBaseView(object):
    def dispatch(self, request, *args, **kwargs):
        print('before')
        ret = super().dispatch(request, *args, **kwargs)
        print('after')
        return ret

class StudentView(MyBaseView,View):
    def get(self,request,*args,**kwargs):
        print('get方法')
        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')

通过在views中重写dispath方法,
实现在执行父类dispath方法之前和之后分别打印before和after
MyBaseView没有父类,但是它的dispatch方法是来自StudentView的父类View里面,也就是说super不仅仅是调用自己父类的方法,同时也会去寻找自己子类的其他父类里面是否有这个方法,有就调用。

通常在程序的设计中,如果涉及到重复的逻辑代码,需要多个类公用,则把它写成基类,其他类通过继承的方式获得这个办法。

CSRF

原理

对于POST请求,需要有CSRF token

CSRF token在django中是基于中间件实现的,django的中间件里面最多可以写5个方法

  • process_request
  • process_view
  • process_response
  • process_exception
  • process_render_template

中间件的执行流程:
image.png
使用中间件可以完成:

  • 权限
  • 用户登录验证
  • csrf_token
    > csrf_token放在了process_view里面,因为默认的django.middleware.csrf.CsrfViewMiddleware匹配全局都要完成CSRF认证,但是如果在某个函数前面加上装饰器@csrf_exempt(from django.views.decorators.csrf import csrf_exempt)就可以让这个函数免除csrf的认证。
    >
    > process_view主要检查了视图是否被装饰(来免除CSRF认证),同时去请求体或cookie中获取token

源码

情况1:

MIDDLEWARE = [
    'django.middleware.security.SecurityMiddleware',
    'django.contrib.sessions.middleware.SessionMiddleware',
    'django.middleware.common.CommonMiddleware',
    'django.middleware.csrf.CsrfViewMiddleware',  # 全局csrf认证
    'django.contrib.auth.middleware.AuthenticationMiddleware',
    'django.contrib.messages.middleware.MessageMiddleware',
    'django.middleware.clickjacking.XFrameOptionsMiddleware',
]

from django.views.decorators.csrf import csrf_exempt
# Create your views here.

@csrf_exempt  #表明该函数无需认证
def user(request):
    user_list = ['alex','bobby']
    return HttpResponse(user_list)

情况2:

MIDDLEWARE = [
    'django.middleware.security.SecurityMiddleware',
    'django.contrib.sessions.middleware.SessionMiddleware',
    'django.middleware.common.CommonMiddleware',
    # 'django.middleware.csrf.CsrfViewMiddleware',  #全局不进行csrf认证
    'django.contrib.auth.middleware.AuthenticationMiddleware',
    'django.contrib.messages.middleware.MessageMiddleware',
    'django.middleware.clickjacking.XFrameOptionsMiddleware',
]

from django.views.decorators.csrf import csrf_protect
# Create your views here.

@csrf_protect  #该函数需要csrf token的认证
def user(request):
    user_list = ['alex','bobby']
    return HttpResponse(user_list)

如果需要给CBV加上装饰器需要加在dispatch方法上,在单独的方法上更改无效。

from django.utils.decorators import method_decorator
# Create your views here.

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

或者

from django.utils.decorators import method_decorator
# Create your views here.

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

版权声明:本文为原创文章,版权归 heroyf 所有。
本文链接: https://heroyf.club/2019/07/django_learn1/


“苹果是给那些为了爱选择死亡的人的奖励”