美文网首页
2019-01-02

2019-01-02

作者: Karl_2c80 | 来源:发表于2019-01-02 16:34 被阅读0次

    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示例代码

    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

          本文链接:https://www.haomeiwen.com/subject/fmkzlqtx.html