zoukankan      html  css  js  c++  java
  • 关于Django中登录认证的方式:

    关于method_decorator的作用,以及不再使用method_decorator为装饰器,添加self

    1.method_decorator的作用:

    为函数视图装饰器补充第一个参数self,以适配类视图的方法;

    如果装饰器本身就可以适配类视图的方法,就无须再使用method_decorator

    def my_decorator(view_func):
    	def wrapper(request,*args,**kwargs):
            print('装饰器被调用')
            print(request.path)
            return view_func(request,*args,**kwargs)
        return wrapper
    
    #method_decorator装饰器为函数视图装饰器(就是wrapper)补充第一个self参数,以适配类视图方法
    @method_decortaor(my_decorator,name='disatch')
    class DemoView(View):
        def get(self,request):
            return HttpResponse('aaa')
        def post(self,request):
            return HttpResponse('bbb')
    
    

    我们可以自己补充self,就不再使用method_decorator

    def my_decorator(view_func):
        def wrapper(self,request,*args,**kwargs):
            print('装饰器被调用')
            print(request.path)
            return view_func(self,request,*args,**kwargs)
        return wrapper
    
    @my_decorator
    class DemoView(View):
        def get(self,request):
            return HttpResponse('aaa')
        def post(self,request):
            return HttpResponse('bbb')
    
    
    
    
    def check_ip(func):
        #实现禁止ip黑名单访问发帖界面.可以通过在视图函数使用装饰器实现
        def wrapper(request,*args,**kwargs):
            #禁止ip黑名单访问
            IP = request.META.get('REMOTE_ADDR')
            if IP in ['192.168.168.11']:
                return HttpResponse("此IP禁止访问")
            return func(request,*args,**kwargs)
        return wrapper
    

    补充一个login_required -- 登录验证装饰器:

    源码:

    def login_required(function=None, redirect_field_name=REDIRECT_FIELD_NAME, login_url=None):
        """
        Decorator for views that checks that the user is logged in, redirecting
        to the log-in page if necessary.
        """
        actual_decorator = user_passes_test(
            lambda u: u.is_authenticated,
            login_url=login_url,
            redirect_field_name=redirect_field_name
        )
        if function:
            return actual_decorator(function)
        return actual_decorator
    
    # user_passes_test源码
    def user_passes_test(test_func, login_url=None, redirect_field_name=REDIRECT_FIELD_NAME):
        """
        Decorator for views that checks that the user passes the given test,
        redirecting to the log-in page if necessary. The test should be a callable
        that takes the user object and returns True if the user passes.
        """
    
        def decorator(view_func):
            @wraps(view_func)
            def _wrapped_view(request, *args, **kwargs):
                if test_func(request.user):
                    return view_func(request, *args, **kwargs)
                path = request.build_absolute_uri()
                resolved_login_url = resolve_url(login_url or settings.LOGIN_URL)
                # If the login url is the same scheme and net location then just
                # use the path as the "next" url.
                login_scheme, login_netloc = urlparse(resolved_login_url)[:2]
                current_scheme, current_netloc = urlparse(path)[:2]
                if ((not login_scheme or login_scheme == current_scheme) and
                        (not login_netloc or login_netloc == current_netloc)):
                    path = request.get_full_path()
                from django.contrib.auth.views import redirect_to_login
                return redirect_to_login(
                    path, resolved_login_url, redirect_field_name)
            return _wrapped_view
        return decorator
    
    
    #1.直接在类的视图中写登录校验实现:
    """
    Django用户认证系统提供了request.user.is-authenticated()来判断用户是否登录,如果登录返回True,反之,返回False;
    
    缺点:登录认证逻辑需要地方太多,代码重复多次
    """
    class UserInfoView(View):
        '''用户中心'''
        def get(self,request):
            '''个人信息界面'''
            if request.user.is_authenticated():
                return render(request,'user_center_info.html')
            else:
                return redirect(reverse('users:login'))
    
            
    #2.1(URLconf装饰使用方法)对路由中的as_view()使用装饰器:login_required
    '''在定义路由时添加:'''
    url(r'^info/$',login_required(views.UserinfoView.as_view()),name='info')
    
    #2.2装饰基于函数的视图
    from django.contrib.auth.decorators import login_required
    from django.http import HttpResponse
    
    @login_required
    def my_view(request):
        if request.method == 'GET':
            return HttpResponse('result')
        
    #2.3装饰类的视图
    from django.contrib.auth.decorators import login_required
    from django.utils.decorators import method_decorator
    from django.views.generic import TemplateView
    
    class ProtectedView(TempalteView):
        template_name = 'secret.html'
        @method_decorator(login_required)
        def dispatch(self,*args,**kwargs):
            return super(ProtectedView,self).dispatch(*args,**kwargs)
        
        
    # 2.4 装饰通过Mixin类继承来实现:
    from django.contrib.auth.decorators import login-required
    from django.http import HttpResponse
    from django.shortcuts import render
    from django.views.generic import View
    from .forms import MyForm
    
    class LoginRequiredMixin(object):
        @classmethod
        def as_view(cls,**kwargs):
            view == super(LoginRequiredMixin,cls).as_view(**initkwargs)
            return login_required(view)
        
        
    class MyFormView(LoginRequiredMixin,View):
        form_class = MyForm
        initial = {'key':'value'}
        template_name = 'form_template.html'
        
        def get(self,request,*args,**kwargs):
            form = self.form_class(initial = self.initial)
            return render(request,self.template_name,{'form':form})
        
    
    #3.定义验证用户是否登录扩展类
    '''使用Django自带的login_required装饰器来完成扩展,完成扩展后需要该功能的视图只需多继承该类就可以,复用率很高'''
    
    #自定义的工具目录:
    from django.contrib.auth.decorator import login_required
    
    class LoginRequiredMinxin(object):
        @classmethod
        def as_view(cls,**kwargs):
            view = super().as_view(**kwargs)
            return login_required(view)
    #使用时导包,并同时继承自定义类LoginRequiredMixin和View即可:
    class UserInfoView(LoginRequiredMixin,View):
        '''用户中心'''
        def get(self,request):
            '''个人信息页面'''
            return render(request,'user_center_info.html')
    
        
    '''
    3.1装饰器login_required会自带next参数,和重定向地址,用于登陆后跳转以及不满足登录状态的重定向地址;
    3.2 如果未设置登录验证则被重定向到LOGIN_URL配置(settings.py)项指定的地址;
    3.3 在设置文件添加如下配置:表示当前用户未通过登录验证时,将用户重定向到/login/登录页面,LOGIN_URL = '/login/'
    3.4 若不设置,默认未通过的登录验证时跳转路径是:/account/login/
    3.5 跳转后的next参数,帮助用户完成登录后,自动跳转回登录前的页面
    
    
    '''
    
  • 相关阅读:
    centos7.5搭建zabbix3.4.x以及mysql定制化监控
    dockerfile 的常用讲解
    使用nginx快速搭建文件服务器
    centos7 安装ELK
    centos7 安装Gitlab
    centos7 安装jenkins
    ansible-playbook使用详解
    DNS主从配置
    ansible 安装部署文档
    WPF Grid MouseWheel事件无法触发
  • 原文地址:https://www.cnblogs.com/Zhao159461/p/12528961.html
Copyright © 2011-2022 走看看