1. 程式人生 > 其它 >函式和類相關知識點

函式和類相關知識點

重寫類中的某個方法

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')