函数和类相关知识点


重写类中的某个方法

from django.utils.decorators import method_decorator


class HomeView(View):
	#这里重写了父类中的dispatch方法,原来的方法中需要参数,重写后的方法也应该需要传入参数,原来的方法有返回值,
    #重写后,这个方法也应该有返回值.这里没有进行其他操作,只是调用了父类中的dispatch方法,
    def dispatch(self, request, *args, **kwargs):
        return super(HomeView, self).dispatch(request, *args, **kwargs)

    def get(self, request):
        return render(request, "home.html")
    
    @method_decorator(check_login)
    def post(self, request):
        print("Home View POST method...")
        return redirect("/index/")

装饰器

给函数加装饰器

from functools import wraps
#func为被装饰的函数,内层函数对外层函数中的非全局变量进行引用和使用,这个变量为自由变量,他在内存中不会消失。
#并且外层函数返回内层函数名,这样的结构叫做装饰器。
def check_login(func):
    @wraps(func)
    def inner(request, *args, **kwargs):
        next_url = request.get_full_path()
        if request.session.get("user"):
            return func(request, *args, **kwargs)
        else:
            return redirect("/login/?next={}".format(next_url))
    return inner

def login(request):
    if request.method == "POST":
        user = request.POST.get("user")
        pwd = request.POST.get("pwd")

        if user == "alex" and pwd == "alex1234":
            # 设置session
            request.session["user"] = user
            # 获取跳到登陆页面之前的URL
            next_url = request.GET.get("next")
            # 如果有,就跳转回登陆之前的URL
            if next_url:
                return redirect(next_url)
            # 否则默认跳转到index页面
            else:
                return redirect("/index/")
    return render(request, "login.html")

@check_login#写下函数的上方,等价于这种形式logout=check_login(logout),=inner,将返回的内层函数赋值给logout,函数名具有地址属性,下次你在调用这个logout函数实际上是调用了内层函数,
def logout(request):
    # 删除所有当前请求相关的session
    request.session.delete()
    return redirect("/login/")

@check_login
def index(request):
    current_user = request.session.get("user", None)
    return render(request, "index.html", {"user": current_user})

注意:子函数形式

def check_login(func):
    def inner(*args, **kwargs):
        print(666)
    inner()
    
    #这样的结构,在函数内部再定义一个函数,这个函数是子函数,这个inner函数就是个普通的函数,但是inner函数只能够在这个函数内部被调用,二不能被外部调用。

在CBV视图中,给类中的方法添加装饰器

方式一:给类中的视图函数添加装饰器

from django.utils.decorators import method_decorator


class HomeView(View):

    def dispatch(self, request, *args, **kwargs):
        return super(HomeView, self).dispatch(request, *args, **kwargs)

    def get(self, request):
        return render(request, "home.html")
    
    @method_decorator(check_login)#多了个这种形式,但是仍然可以理解为给函数添加装饰器post=check_login(post),仍然可以看成这种形式。在执行这个视图函数之前进行登陆验证下
    def post(self, request):
        print("Home View POST method...")
        return redirect("/index/")

方式二:加在dispatch方法上

rom django.utils.decorators import method_decorator
#dispatch方法会根据不同的请求方法,然后调用类中相应的方法,如果是POST请求,则会调用post方法。然后把request和分组匹配结果作为参数传过去。
#给dispatch方法添加装饰器,是先进行登陆验证,再调用相应的方法
#给类中的视图函数添加装饰器,是直接调用了这个‘函数’,在函数中进行登陆验证,然后执行相应的操作

class HomeView(View):

    @method_decorator(check_login)
    def dispatch(self, request, *args, **kwargs):
        return super(HomeView, self).dispatch(request, *args, **kwargs)
    def get(self, request):
        return render(request, "home.html")

    def post(self, request):
        print("Home View POST method...")
        return redirect("/index/")

方式三:直接加在视图类上,但method_decorator必须传 name 关键字参数,说明我要给这个类中的哪个方法添加装饰器。如果get方法和post方法都需要登录校验的话就写两个装饰器。

from django.utils.decorators import method_decorator

@method_decorator(check_login, name="get")#给类中的get方法添加装饰器
@method_decorator(check_login, name="post")#给类中的post方法添加装饰器
class HomeView(View):

    def dispatch(self, request, *args, **kwargs):
        return super(HomeView, self).dispatch(request, *args, **kwargs)

    def get(self, request):
        return render(request, "home.html")

    def post(self, request):
        print("Home View POST method...")
        return redirect("/index/")

补充:

在html中写上{%csrf_token%}就能过csrftoken认证系统,还有一种方法也可以过csrf_token认证,那就是给视图函数加上装饰器。

CSRF Token相关装饰器在CBV只能加到dispatch方法上,或者加在视图类上然后name参数指定为dispatch方法。

备注:

? srf_protect,即便settings中没有设置全局中间件,即注销了settings里面的csrfmiddlewaretoken认证。也为当前函数强制设置csrftoken认证。---->不允许跨站请求,强制保护

  csrf_exempt,取消当前函数防跨站请求伪造功能,即便settings中设置了全局中间件------>允许跨站请求,强制取消保护

from django.views.decorators.csrf import csrf_exempt, csrf_protect
from django.utils.decorators import method_decorator


class HomeView(View):

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

    def get(self, request):
        return render(request, "home.html")

    def post(self, request):
        print("Home View POST method...")
        return redirect("/index/")

或者

from django.views.decorators.csrf import csrf_exempt, csrf_protect
from django.utils.decorators import method_decorator


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

    def get(self, request):
        return render(request, "home.html")

    def post(self, request):
        print("Home View POST method...")
        return redirect("/index/")

在视图函数中

@csrf_exempt#允许跨站请求,就不需要csrftoken认证啦
def func2(request):
    if request.method=='GET':
        return render(request, 'xx.html')
    else:
        username=request.POST.get('username')
        print(username)
        return HttpResponse('ok')
@csrf_protect#强制保护
def func2(request):
    if request.method=='GET':
        return render(request, 'xx.html')
    else:
        username=request.POST.get('username')
        print(username)
        return HttpResponse('ok')


相关