CBV实现登录验证
----------------应用:登录验证
继承:
单继承:
# class BaseView(View):
# def dispatch(self, request, *args, **kwargs):
# if request.session.get('username'):
# response = super(BaseView,self).dispatch(request, *args, **kwargs)
# return response
# else:
# return redirect('/login.html')
#
# class IndexView(BaseView):
#
# def get(self,request,*args,**kwargs):
# return HttpResponse(request.session['username'])
写一个类继承VIEW 调用View 的dispath 函数之前做一个 session验证
多继承:
# 多继承方式:
# class BaseView(object):
# def dispatch(self, request, *args, **kwargs):
# if request.session.get('username'):
# response = super(BaseView,self).dispatch(request, *args, **kwargs)
# return response
# else:
# return redirect('/login.html')
#
# class IndexView(BaseView,View):
#
# def get(self,request,*args,**kwargs):
# return HttpResponse(request.session['username'])
和上面的方法原理相同, 自己写的类BaseView不继承任何类, 然后主类 继承 自己写的类 和 View 类,BaseView中的super方法 会找到 View 中的dispath
装饰器:
def auth(func):
def inner(request,*args,**kwargs):
if request.session.get('username'):
obj = func(request,*args,**kwargs)
return obj
else:
return redirect('/login.html')
return inner
# @method_decorator(auth,name='get')
class IndexView(View):
@method_decorator(auth)
def dispatch(self, request, *args, **kwargs):
if request.session.get('username'):
response = super(IndexView,self).dispatch(request, *args, **kwargs)
return response
else:
return redirect('/login.html')
@method_decorator(auth)
def get(self,request,*args,**kwargs):
return HttpResponse(request.session['username'])
@method_decorator(csrf_exempt) # 无效
def post(self,request,*args,**kwargs):
return HttpResponse(request.session['username'])
要注意俩点:
1:用的 CBV 的话 需要导入 from django.utils.decorators import method_decorator 之后@method_decorator(auth)
放在函数名上, 如果放在类上需要加个参数 @method_decorator(auth,name='get') ,说明是 给 get函数使用
2:但是django有个BUG 装饰器方法都会出现 CSRF问题 ,所以
需要写一个dispath方法 直接调用VIEW里面的 dispath 进行反射@method_decorator(auth) 放在 dispath上面
<1>FBV示例代码
- views.py
# Create your views here.
# -*- coding: utf-8 -*-
from django.shortcuts import render,render_to_response
from django.http import HttpResponseRedirect
from django.contrib import auth
from django.template import RequestContext
from webserver.forms import UserForm,RegisterForm
import time
#登录验证
def login(req):
nowtime = time.strftime("%Y-%m-%d %H:%M:%S", time.localtime())
if req.method == 'GET':
uf = UserForm()
return render_to_response('login.html', RequestContext(req, {'uf': uf,'nowtime': nowtime }))
else:
uf = UserForm(req.POST)
if uf.is_valid():
username = req.POST.get('username', '')
password = req.POST.get('password', '')
user = auth.authenticate(username = username,password = password)
if user is not None and user.is_active:
auth.login(req,user)
return render_to_response('index.html', RequestContext(req))
else:
return render_to_response('login.html', RequestContext(req, {'uf': uf,'nowtime': nowtime, 'password_is_wrong': True}))
else:
return render_to_response('login.html', RequestContext(req, {'uf': uf,'nowtime': nowtime }))
urls.py
from django.conf.urls import *
from webserver import views
urlpatterns = [
url(r'^login/$',views.login),
]
login.html
{% load staticfiles %}
<link href="{% static "css/adstyle.css"%}" rel="stylesheet" type="text/css" />
<html>
<head>
<meta http-equiv="Content-Type" content="text/html; charset=utf-8" />
<title>Login</title>
</head>
{% if password_is_wrong %}
<script type="text/javascript" src="{%static "js/jquery-1.11.0.min.js" %}"></script>
<script type="text/javascript" src="{%static "js/alert.js" %}"></script>
<link href="{%static "css/alert.css" %}" rel="stylesheet" type="text/css" />
<script type="text/javascript">
Alert.showMsg("错误!!用户名或密码错误!");
location.href="/webserver/login/"
</script>
{% endif %}
<body>
<div class="admin-ht" style="background: url(/static/images/lo.jpg);">
<div class="adminBord">
<h1>运维管理平台</h1>
<h4>{{ nowtime }}</h4>
<form method="post" enctype="multipart/form-data" >
{% csrf_token %}
{{uf.as_p}}
<input type="submit" value="login" id="loging">
</form>
</div>
</div>
</body>
</html>
<2> CBV示例代码
- urls.py
urlpatterns = [
url(r'^admin/', admin.site.urls),
url(r'^index/', views.IndexView.as_view()) # 执行类后面的as_view()方法,是父类里面的方法
]
- views.py
from django.views import View
class IndexView(View):
# 以get形式访问会执行get函数,一般情况下获取数据
def get(self, *args, **kwargs):
return HttpResponse('666')
# 以post形式访问的话会执行post函数,一般情况下发送数据
def post(self, *args, **kwargs):
return HttpResponse('999')
-
CBV重新定义dispatch函数
所有的方法本质上都是通过dispatch这个函数反射执行,如果想要在执行get或post方法前执行其他步骤,可以重写dispatch
class IndexView(View):
# 重写父类的dispatch方法,如果不重写,他会执行父类的dispatch方法,
def dispatch(self, request, *args, **kwargs):
print('before')
res = super(IndexView, self).dispatch(request, *args, **kwargs)
print('after')
return res
# 以get形式访问会执行get函数
def get(self, *args, **kwargs):
return HttpResponse('666')
# 以post形式访问的话会执行post函数
def post(self, *args, **kwargs):
return HttpResponse('999')
- 添加用户登录验证
from django.shortcuts import render, HttpResponse, redirect
from django.views import View
class LoginView(View):
def get(self, request):
return render(request, 'login.html')
def post(self, request):
user = request.POST.get('user')
pwd = request.POST.get('pwd')
if user == 'rdw' and pwd == '666':
request.session['user_info'] = 'rdw'
return redirect('/index/')
else:
return render(request, 'login.html')
class IndexView(View):
# 重写父类的dispatch方法,如果不重写,他会执行父类的dispatch方法,
def dispatch(self, request, *args, **kwargs):
if not request.session.get('user_info'):
return redirect('/login/')
res = super(IndexView, self).dispatch(request, *args, **kwargs)
return res
# 以get形式访问会执行get函数
def get(self, request, *args, **kwargs):
return render(request, 'index.html')
# 以post形式访问的话会执行post函数
def post(self, *args, **kwargs):
return HttpResponse('999')
-
给视图类添加装饰器
如果有多个程序需要用户登录验证的话会造成代码冗余,可以使用继承很好的解决这个问题,但是还有更好的方法,那就是基于装饰器实现登录验证
<1> 定义装饰器
def login_test(func):
def inner(request, *args, **kwargs):
if not request.session.get('user_info'):
return redirect('/login/')
return func(*args, **kwargs)
return inner
<2> 直接添加在dispatch里面,这样每个函数都会执行
from django.utils.decorators import method_decorator
@method_decorator(login_test)
def dispatch(self, request, *args, **kwargs):
res = super(IndexView, self).dispatch(request, *args, **kwargs)
return res
<3> 添加在每一个函数中
from django.utils.decorators import method_decorator
@method_decorator(login_test)
def get(self, request, *args, **kwargs):
return render(request, 'index.html')
<4> 直接添加在类上,后面的name表示只给get添加装饰器
from django.utils.decorators import method_decorator
@method_decorator(login_test, name='get')
class IndexView(View):
注意
1)添加装饰器前必须导入from django.utils.decorators import method_decorator
2)添加装饰器的格式必须为@method_decorator(),括号里面为装饰器的函数名
3)给类添加是必须声明name
4)注意csrf-token装饰器的特殊性,它只能加在dispatch上面
网友评论