0001.关于django中的Mixin以及原理解析

本文介绍如何在Django中使用类视图实现login_required功能,并详细解析其内部原理。同时,展示了如何自定义装饰器限制非管理员用户的访问。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

废话不讲,只唠干货!

一、引子:在类视图中实现login_required 功能

        在函数视图和类视图中实现login_required功能都臭了了大街了,细节不再描述。仅仅用类视图作为切入点。

    1.定义LoginRequiredMixin实现校验的动作:

class LoginRequiredMixin(object):
    """
    定义LoginRequiredMixin,实现验证用户登录的逻辑
    """
    @classmethod
    def as_view(cls, **initkwargs):
        """
        重写as_view方法,进行校验
        :param initkwargs: 
        :return: 
        """
        view = super(LoginRequiredMixin, cls).as_view(**initkwargs)
        
        return login_required(view)

2.在类视图中继承LoginRequiredMixin

class UserIndexView(LoginRequiredMixin,View):
    def get(self, request):
        return render(request, "user_index.html")

即可实现,只有登录的用户才能访问user_index.html的功能。

二、上面已经实现了LoginRequired的功能,原理是什么?

有些程序员说我知道,不就是在LoginRequiredMixin实现对login_required的封装嘛,这又有什么价值写成博客呢?

不过,你确定你真的知道吗?

那么login_required是如何实现的呢?且听我慢慢道来。

解析django.contrib.auth中的decorators.py

decorators模块中只有定义了3个装饰器函数(user_passes_test、  login_required、  permission_required)

1.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.
    """

源码不再解析,有兴趣的可以去看看。这个函数的主要作用就是对给定的函数进行检测校验。怎么进行具体校验的呢?

以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

login_required实现校验用户是否登录,只要是校验必须有校验的一套规则呀,也就是校验时使用的判定条件。

代码中的 

user_passes_test(

  lambda u: u.is_authenticated(),  

#  判断条件:使用匿名函数进行校验用户是否是登录的,如果是True,就跳转redirect_field_name; 如果是False,就跳转

#   login_url指定的页面。

        login_url=login_url, # 如果验证不通过,进行登录页面的url

        redirect_field_name=redirect_field_name  # 验证通过,跳转的url

        # 其实上面两个参数,就是判断后的两个分歧

    )

三、上面的原理已经简介啦

怎么实现一个自定义的装饰器呢?

需求:一个公司的OA系统,需要自定义管理员模块,不再使用django提供或第三方提供的admin模块。那么,怎么实现普通用户无法访问管理员的控制台的页面呢?

需要对用户的身份进行验证,管理员进行访问,普通用户一边凉快去。

# AdminRequiredMixin 是自定义的Mixin
class AdminIndexView(AdminRequiredMixin, View):
    """实现管理员验证,只有管理员身份才能访问"""

    def get(self, request):
        return render(request, "admin_index.html")

那么AdminRequiredMixin是怎么实现的呢?

# 管理员身份认证     admin_required是自定义的装饰器 
class AdminRequiredMixin(object):
    @classmethod
    def as_view(cls, **initkwargs):
        view = super(AdminRequiredMixin, cls).as_view(**initkwargs)
        return admin_required(view)

admin_required的定义:

from django.contrib.auth.decorators import user_passes_test

# 定义装饰器,
def admin_required(function=None, common_user_url="/user/index"):
    actual_decorator = user_passes_test(
        lambda u: u.is_authenticated() and u.is_superuser,  # 验证条件
        login_url=common_user_url,  # 不满足条件,跳转路径。不要被login_url语言意义迷惑,它的逻辑其实就判断条件False时的跳转路径
        redirect_field_name=None  # 满足条件
    )
    if function:
        return actual_decorator(function)
    return actual_decorator

注意:login_url =common_user_url,  # 不满足条件,跳转路径。

不要被login_url语言意义迷惑,它的逻辑其实就判断条件(lambda u: u.is_authenticated() and u.is_superuser)为False时的跳转路径。因为源代码实现的逻辑一般都是不满足判断条件,那就重新登录吧。所以把参数名命名为login_url 。而我们的逻辑是普通用户不能访问管理员页面,一旦访问跳转到用户主页面或者是其他提示性页面(如:提醒“非管理员权限不得访问”等),所以依旧把common_user_url 传递给login_url.




          

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值