2019-01-02

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 %}



    
    Login

{% if password_is_wrong %}
    
    
    
    
{% endif %}

    

运维管理平台

{{ nowtime }}

{% csrf_token %} {{uf.as_p}}

<2> CBV示例代码

  1. urls.py
urlpatterns = [
    url(r'^admin/', admin.site.urls),
    url(r'^index/', views.IndexView.as_view())     # 执行类后面的as_view()方法,是父类里面的方法
]
  1. 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上面

你可能感兴趣的:(2019-01-02)