Django中Admin管理与权限管理(三)————模块的鉴权操作

来源:互联网 发布:粤语学软件哪个好 编辑:程序博客网 时间:2024/06/13 01:13
通知模块的鉴权操作
1.定义权限
这里需要给大家提的是,在我们新建模型完成之后,系统会自动的给这个模型定义三个权限。我们可以通过认证和授权中的组来进行查看。
如下图所示,我们可以看到默认添加的三个权限信息。


当然啦,在实际运行环境中,我们难免要对权限进行扩展。所以我们就需要自定义自己需要的权限了。
下面就来介绍自定义权限的过程。方法很简单,在我们自定义的GfzNotice中添加permissions。我们这里只新增了一个属性,当然了,你可以添加多个属性,属性之间以英文符号逗号分割。
# 定义Notice模型
class GfzNotice(models.Model):
    ...
    class Meta:
        ...
        permissions = (
            ("scan_noticee", u"查看通知"),
        )
修改完成后保存,然后按照附录1的3中所示内容完成数据库的同步。再次查看权限列表时,我们就可以看到notice/通知下面多了一个可以选择的权限,叫做查看通知了。


2.权限的配置
1.分配到组(Group)
这里需要给大家说的是,将权限分配到组的话,就是这个组拥有哪些权限,这个人就拥有哪些权限。具体组的权限配置如下:


将要分配的权限放在右边,然后上面可以自定义一个方便管理的名称,我们这里就定义了一个通知管理组。接下来就是给将组的权限分配给个人。
按照下图所示,将要分配的组移动到右边选中的组中,之后点击保存即可完成相关权限配置过程。


2.分配到个人
有了前面将权限分配到组的过程后,接下来将权限分配给个人就显得十分简单了。如下图所示,我们只把查看通知的权限分配给个人的话,只需要选中,点击右下角的保存按钮即可。


3.权限的使用
前面我们已经了解了权限的定义和配置的相关过程,接下来需要我们完成的就是权限怎么使用了。我们主要会围绕下面几个步骤带大家一起来完成权限的配置和使用过程。
1.设置路由
首先我们在主的路由(fz应用下的urls.py文件)添加如下配置:
urlpatterns = [
    ...
    # 通知入口
    url(r'^notice/', include('notice.urls')),
]
这样所有对notice的请求都会交给notice应用下的urls来处理了。
这时我们再来配置notice下的urls.py文件:
# -*- coding:utf-8 -*-
from django.conf.urls import url
from . import views
urlpatterns = [
    # add by chr 20160719
    # 针对于什么值都不传递过来的情况
    url(r'^$', views.home, name='home'),
    # 传递不带/的值 进行处理
    url(r'^(?P<slug>\w+)$', views.URLControl.as_view(), name='urlControl'),
    # 传递带/的值 进行处理
    url(r'^(?P<slug>\w+)/$', views.URLControl.as_view(), name='urlControl'),
]
这里我们主要对三种情况进行鉴权,一种是什么值都没传过来,一种是传了参数但没有带/,还有一种就是穿了参数且带了/。
2.编写View.py(接口鉴权)
对于View.py中鉴权的方式大体上分为3中,第一种是在函数前添加修饰符@login_required,第二种方式是在函数的具体实现过程中利用是否验证的属性判断,即request.user.is_authenticated()是否为true,这两种方式都是限定了没有登录的用户是返回不了值的。第三种方式也是加修饰符,但这个是对已经登录的用户做的限制,修饰符的内容是permission_required+具体要判断的权限的值。
# -*- coding:utf-8 -*-
from django.shortcuts import render, get_object_or_404
from django.http import Http404, HttpResponseRedirect
from django.views.generic import View
from django.core.exceptions import PermissionDenied
from django.contrib.auth.decorators import login_required
from notice.models import GfzNotice
from django.contrib.auth.decorators import permission_required
# Create your views here.
# add by chr 20160719
# 返回主页面
@login_required
def home(request):
    noticelist = GfzNotice.objects.order_by('list_order')
    return render(request, 'notice/home.html', {'noticelist': noticelist})
# 路由控制
class URLControl(View):
    # API处理
    def post(self, request, *args, **kwargs):
        # 获取要对用户进行什么操作
        raise PermissionDenied
    # 页面处理
    def get(self, request, *args, **kwargs):
        if not request.user.is_authenticated():
            return HttpResponseRedirect('/login')
        slug = self.kwargs.get('slug')
        if slug[0:4] == 'view':
            return getNotice(request, slug[4:])
        # 如果是get请求直接返回404页面
        raise Http404
@permission_required('notice.scan_noticee')
def getNotice(request, iobj):
    detailnotice = get_object_or_404(GfzNotice, pk = iobj)
    return render(request, 'notice/detail.html', {'detailnotice': detailnotice})
3.页面鉴权
页面中进行授权的方式也很简单,添加{% if perms.notice.scan_noticee %}这句话的意思就是判断当前用户是否有notice下的scan_noticee权限。
{% extends "./accounts/base.html"%}
{% block title %}
    <title>通知列表</title>
{% endblock %}
{% block main %}
<div class="wrapper">
    <div class="content-wrapper" style="min-height: 1036px;">
    <!-- Content Header (Page header) -->
    <section class="content-header">
      <h1>
        通知管理
        <small>系统最新的通知</small>
      </h1>
    </section>
    <!-- Main content -->
    <section class="content">
      <!-- COLOR PALETTE -->
      <div class="box box-default color-palette-box">
        <div class="box-header with-border">
          <h3 class="box-title"><i class="fa fa-tag"></i> 最新的通知 </h3>
        </div>
          <div class="box-body">
              {% if perms.notice.scan_noticee %}
              <table class="table table-bordered">
                <tbody><tr>
                  <th style="width: 10px">#</th>
                  <th>通知</th>
                  <th>发布时间</th>
                  <th>发布人</th>
                  <th>修改时间</th>
                </tr>
                 {% for notice in noticelist %}
                <tr>
                  <td>1.</td>
                  <td><a class="txtlink" href="/notice/view{{notice.id}}">{{notice.title}}</a></td>
                  <td>{{notice.date_create}}</td>
                  <td>{{notice.crate_man}}</td>
                  <td>{{notice.date_mod}}</td>
                </tr>
                {% endfor %}
              </tbody></table>
               {% else %}
                    你没有访问该模块的权限哦
               {% endif %}
          </div>
      </div> 
 <div>
</div>
    </section>
    <!-- /.content -->
  </div>
</div>
{% endblock %}
4.单元测试
具体单元测试的内容,请参考代码中的注释,这里不做细讲。测试的内容还是分成了三步 第一测试没有登录的用户;第二测试已经登录的用户,因为在第二步中需要测试通知的详细页,所以要往通知表中插入一条记录,同时这一步中需要创建两个用户,一个有权限,一个没有权限分别进行测试;最后一个就是注销之后再进行相关测试了。
# -*- coding:utf-8 -*-
from django.shortcuts import get_object_or_404
from django.test import TestCase
from django.test.utils import setup_test_environment
from django.test import Client
from accounts.models import FzjUser
from notice.models import GfzNotice
# Create your tests here.
# add by chr 20160719
class HomeTest(TestCase):
    def testApis(self):
        setup_test_environment()
        client = Client()
        # 对于没有登录的用户进行单元测试
        response = client.get('/notice')
        self.assertEqual(response.status_code, 301)
        response = client.get('/notice/')
        self.assertEqual(response.status_code, 302)
        response = client.get('/notice/view1')
        self.assertEqual(response.status_code, 302)
        response = client.get('/notice/view1/')
        self.assertEqual(response.status_code, 302)
        # 给临时数据库创建一个登录账号 用户名为chr 密码为123 --- 该用户为超级管理员
        FzjUser.objects.create_superuser(username='chr', password='123', email='')
        # 新增一条通知记录 方便下面进行接口的测试
        gfzNotice = GfzNotice()
        gfzNotice.title = 'test'
        gfzNotice.content = 'test'
        gfzNotice.crate_man = get_object_or_404(FzjUser, pk = 1)
        gfzNotice.date_mod = '2016/7/19'
        GfzNotice.save(gfzNotice)
        # 使用刚创建的用户信息登录系统平台 如果登录出错 测试会报错
        self.assertEqual(client.login(username='chr', password='123'), True)
        # 下面就以登录成功的用户来完成相关的操作 对于存在的接口返回200
        response = client.get('/notice')
        # 重转向到/notice/
        self.assertEqual(response.status_code, 301)
        response = client.get('/notice/')
        self.assertEqual(response.status_code, 200)
        response = client.get('/notice/view1')
        self.assertEqual(response.status_code, 200)
        response = client.get('/notice/view1/')
        self.assertEqual(response.status_code, 200)
        # 对于不存在的接口返回404 没有找到
        response = client.get('/notice/getOther')
        self.assertEqual(response.status_code, 404)
        response = client.get('/notice/getOther/')
        self.assertEqual(response.status_code, 404)
        # 将登录的账号登出 然后重新测试相关接口
        client.logout()
        # 给临时数据库创建一个登录账号 用户名为chr 密码为123 --- 该用户为普通用户
        FzjUser.objects.create_user(username='chr23899', password='123', email='')
        # 使用刚创建的用户信息登录系统平台 如果登录出错 测试会报错
        self.assertEqual(client.login(username='chr23899', password='123'), True)
        # 下面就以登录成功的用户来完成相关的操作 对于存在的接口返回200
        # 跳转到 /notice/ 目录下
        response = client.get('/notice')
        self.assertEqual(response.status_code, 301)
        response = client.get('/notice/')
        self.assertEqual(response.status_code, 200)
        # 没有权限访问 导致跳转
        response = client.get('/notice/view1')
        self.assertEqual(response.status_code, 302)
        response = client.get('/notice/view1/')
        self.assertEqual(response.status_code, 302)
        # 对于不存在的接口返回404 没有找到
        response = client.get('/notice/getOther')
        self.assertEqual(response.status_code, 404)
        response = client.get('/notice/getOther/')
        self.assertEqual(response.status_code, 404)
        # 将登录的账号登出 然后重新测试相关接口
        client.logout()
        response = client.get('/notice/view1')
        self.assertEqual(response.status_code, 302)
        response = client.get('/notice/view1/')
        self.assertEqual(response.status_code, 302)
到这单元测试的部分就算完成了,接下来我们执行以下单元测试:出现了下面的结果。恭喜你,单元测试的结果是成功的了。


5.实现效果
1.对于有权限的用户:
访问通知列表的时候可以看到如下图所示的内容。


对于通知详情的话,就可以看到下面的效果


2.对于没有权限的用户:
这是访问通知列表的时候,就出现了“你没有访问该模块的权限哦”,这就是在页面中设置的相关鉴权。


如果这是通过地址http://127.0.0.1:8000/notice/view1去获取通知的详情页面的话,这个用户是获取不到的,因为我们在View.py中对详细的函数进行了权限的控制。
4.小结
通过学习,我们已经对django自带的鉴权有了很好的了解和掌握了。
1 0
原创粉丝点击