函数和类相关知识点
重写类中的某个方法
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')