装饰器decorator实现Django的访问和权限控制


前言

最近在复习django时发现了装饰器的相关内容,觉得挺有意思的,为此做下记录。

一、装饰器语法

先说明一下装饰器,python的装饰器类似于java的注解,可以用在方法上面。按我的理解,被装饰器装饰的方法,其实是先执行装饰器里面的代码,然后再执行方法里面的代码。语法如下:

def 装饰器名字(传入方法名):
    # 这个函数名字随便起,下面返回的函数名要和这个函数名一致
    def 执行函数名(传入方法的参数列表):
    	# 你想做的操作
    	........
    	# 返回传入方法
        return 传入方法名(传入方法的参数列表)
    # 返回执行函数
    return 执行函数

二、装饰器解释

下面举个例子,decorator_count是我自定义的一个装饰器

def decorator_count(func):
    def dec_count(i, j):
        print("装饰器代码已执行")
        return func(i, j)
    return dec_count


@decorator_count
def count(i, j):
    print(i+j)


if __name__ == '__main__':
    count(1, 2)

以上程序的执行结果是:

装饰器代码已执行
3

为什么结果是这样,其实count()方法给装饰器装饰之后,装饰器里面的代码和下面代码类似:

# 这里参数变了
def decorator_count(count):
    def dec_count(i, j):
        print("装饰器代码已执行")
        # 这里也变了
        return count(i, j)
    return dec_count

这就不难看出,装饰器返回了dec_count()方法,而在dec_count()方法里面,又先执行了print(),再执行count(i, j),所以才会有上面的输出顺序。

三、装饰器实现访问和权限控制

页面的访问是先判断用户是否登录,再返回页面,和上面的先执行print(),再执行count(i, j)是不是很像,那使用装饰器判断用户是否登录就很简单了

1、准备

先准备好有关的模型类,视图和页面,以你的实际项目为准,这里只给出有关的视图方法
自定义装饰器“decorator_logined.py”,判断用户是否已经登录(我这里根据session中是否存在用户名来判断用户是否登录)

from django.shortcuts import redirect


# 装饰器名字
def already_login(func):
    # 这个函数名字随便起,下面返回的函数名要和这个函数名一致
    # 参数列表参考要传入函数
    def alr_login(request, *args, **kwargs):
        un = request.session.get("username")
        # 判断是否已经登录了
        if un:
            return func(request, *args, **kwargs)
        else:
            # 没登录的先登录
            return redirect('/before_index/')
    return alr_login

自定义装饰器“decorator_permission.py”,判断用户是否有权限操作(我这里根据group_id判断用户权限)

from django.http import HttpResponse


def validate_permission(func):
    def valid_per(request, *args, **kwargs):
        # 获取用户所在的用户组id
        group_id = request.session.get('group_id')
        # 判断是否有对应访问权限了
        if group_id == 0:
            return func(request, *args, **kwargs)
        else:
            return HttpResponse("你无权访问!")
    return valid_per

在视图中使用()装饰器用在首页和用户列表:

from django.shortcuts import render, redirect
from .forms import UserForm
from .models import User
from Decorator.decorator_permission import validate_permission
from Decorator.decorator_logined import already_login


# Create your views here.
# 登录
def login(request):
    if request.method == "GET":
        return render(request, "login/login.html")
    if request.method == "POST":
        # 获取数据
        obj = UserForm(request.POST)
        # 校验数据
        if obj.is_valid():
            # 获取obj里面的数据
            user = User.objects.values("id", "username", "group_id").filter(**obj.cleaned_data).first()
            # 在数据库中能找到对应用户
            if user:
                # 将相关信息保存到session中并返回
                request.session['id'] = user['id']
                request.session['username'] = user["username"]
                request.session['group_id'] = user["group_id"]
                # 重定向到首页
                return redirect('/index/')
            else:
                errmsg = {'errmsg': "用户名或者密码错误"}
                return render(request, 'login/login.html', errmsg)
        content = {"obj": obj}
        return render(request, 'login/login.html', content)
# 首页
@already_login
def index(request):
    # 获取用户名已经对应的用户组id
    username = request.session.get("username")
    group_id = request.session.get("group_id")
    content = {"username": username, "group_id": group_id}
    return render(request, 'login/index.html', content)


# 查看用户列表
@already_login
@validate_permission
def userList(request):
    userList = User.objects.all()
    content = {"userList": userList}
    return render(request, "user/user_list.html", content)


# 没登录用户进入首页时的跳转界面
def before_index(request):
    return render(request, "login/before_index.html")

注意:使用多个装饰器装饰同一个方法时装饰器是由上往下依次执行

2、测试

我的用户列表如下,只有group_id为0的用户能访问用户列表:
在这里插入图片描述
没登录时输入首页地址:
在这里插入图片描述
在这里插入图片描述
登录之后输入用户列表地址:
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述
登录管理员账号输入用户列表地址:
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述
大功告成!!!想要判断用户是否登录和用户操作权限,只需要引入对应的装饰器就可以啦。
有什么问题欢迎在评论区留言。

四、附上web页面代码

1、目录结构

在这里插入图片描述

2、代码

1.before_index.html

<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <title>请先登录</title>
</head>
<body>
<h1>请先登录再操作</h1>
<a href="/login/">跳转到登录界面</a>
</body>
</html>

2.index.html

<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <title>首页</title>
</head>
<body>
<h1>首页</h1>
<div>欢迎: {{ username }}</div>
<a href="/login_out/">登出</a>
{% if group_id == 0 %}
    <a href="/userlist/">用户列表</a>
{% endif %}

</body>
</html>

3.login.html

<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <title>登录</title>
</head>
<body>

<div>
    <h2>登录界面</h2>
    <form action="." method="post">
        {% csrf_token %}
        {{ errmsg }}
        用户名: <input name="username">{{ obj.username.errors.0 }}<br>
        密码:   <input name="password">{{ obj.password.errors.0 }}<br>
        <button type="submit">登录</button>
        <a href="/register/">注册</a>
    </form>
</div>
</body>
</html>

4.user_list.html

<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <title>用户列表</title>
</head>
<body>
<h1>用户列表</h1>
{% for user in userList %}
    <li>{{ user.username }}</li>
{% endfor %}
</body>
</html>

代码地址:https://gitee.com/li_weiyan/DjangoReview.git

  • 1
    点赞
  • 7
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值