丛FBC到CBV三(权限)

span::selection, .CodeMirror-line > span > span::selection { background: #d7d4f0; }.CodeMirror-line::-moz-selection, .CodeMirror-line > span::-moz-selection, .CodeMirror-line > span > span::-moz-selection { background: #d7d4f0; }.cm-searching {background: #ffa; background: rgba(255, 255, 0, .4);}.cm-force-border { padding-right: .1px; }@media print { .CodeMirror div.CodeMirror-cursors {visibility: hidden;}}.cm-tab-wrap-hack:after { content: ""; }span.CodeMirror-selectedtext { background: none; }.CodeMirror-activeline-background, .CodeMirror-selected {transition: visibility 0ms 100ms;}.CodeMirror-blur .CodeMirror-activeline-background, .CodeMirror-blur .CodeMirror-selected {visibility:hidden;}.CodeMirror-blur .CodeMirror-matchingbracket {color:inherit !important;outline:none !important;text-decoration:none !important;}.CodeMirror-sizer {min-height:auto !important;}
-->
li {list-style-type:decimal;}.wiz-editor-body ol.wiz-list-level2 > li {list-style-type:lower-latin;}.wiz-editor-body ol.wiz-list-level3 > li {list-style-type:lower-roman;}.wiz-editor-body li.wiz-list-align-style {list-style-position: inside; margin-left: -1em;}.wiz-editor-body blockquote {padding: 0 12px;}.wiz-editor-body blockquote > :first-child {margin-top:0;}.wiz-editor-body blockquote > :last-child {margin-bottom:0;}.wiz-editor-body img {border:0;max-width:100%;height:auto !important;margin:2px 0;}.wiz-editor-body table {border-collapse:collapse;border:1px solid #bbbbbb;}.wiz-editor-body td,.wiz-editor-body th {padding:4px 8px;border-collapse:collapse;border:1px solid #bbbbbb;min-height:28px;word-break:break-word;box-sizing: border-box;}.wiz-editor-body td > div:first-child {margin-top:0;}.wiz-editor-body td > div:last-child {margin-bottom:0;}.wiz-editor-body img.wiz-svg-image {box-shadow:1px 1px 4px #E8E8E8;}.wiz-hide {display:none !important;}
-->

权限

准备数据表

用户组(group)
id group_name
1 usual
2 vip
3 svip
4 admin
用户(user)
id username password group_id
1 Joshua 123 1
2 William 123 2
3 Daniel 123 3
4 Michael 123 4
 
创建项目及app:
                

 
    models.py
 
 
 
19
 
 
 
 
 
1
# -*- coding:utf-8 -*-
2
from django.db import models
3

4
class Group(models.Model):
5
    id = models.AutoField(primary_key=True)
6
    group_name = models.CharField(max_length=40)
7

8
    class Meta:
9
        db_table = 'group'
10

11
class User(models.Model):
12
    id = models.AutoField(primary_key=True)
13
    username = models.CharField(max_length=40,unique=True)
14
    password = models.CharField(max_length=40)
15
    group_id = models.ForeignKey(Group, default=1)
16

17
    class Meta:
18
        db_table = 'user'
19

 
 
views.py
 
 
 
16
 
 
 
 
 
1
from django.http.response import JsonResponse
2
from rest_framework.views import APIView
3

4
from permissions.models import User, Group
5

6

7
class Users(APIView):
8
    def get(self, request):
9
        users = User.objects.all().values()
10
        return JsonResponse(list(users), safe=False)
11

12

13
class Groups(APIView):
14
    def get(self, request):
15
        groups = Group.objects.all().values()
16
        return JsonResponse(list(groups), safe=False)
 
 
 urls.py
 
 
 
9
 
 
 
 
 
1
from django.conf.urls import url
2
from django.contrib import admin
3
from permissions.views import Users, Groups
4

5
urlpatterns = [
6
    url(r'^admin/', admin.site.urls),
7
    url(r'^user/$', Users.as_view(), name='user'),
8
    url(r'^group/$', Groups.as_view(), name='group'),
9
]
 
 
Postman提交请求:
    
             

 
现在新建了一张MemberPrograms表,里面的内容是只给会员用户展示的
实现这个功能:
会员项目(member_programs)
id program_name
1 书法长卷
2 书法碑帖
3 墓志塔铭
4 兰亭集序
 
定义models
 
 
 
6
 
 
 
 
 
1
class MemberProgram(models.Model):
2
    id = models.AutoField(primary_key=True)
3
    program_name = models.CharField(max_length=100)
4

5
    class Meta:
6
        db_table = 'member_program'
 
 
定义url以及视图函数:
 
 
 
9
 
 
 
 
 
1
from django.conf.urls import url
2

3
from permissions.views import Users, Groups, MemberPrograms
4

5
urlpatterns = [
6
    url(r'^user/$', Users.as_view(), name='user'),
7
    url(r'^group/$', Groups.as_view(), name='group'),
8
    url(r'^program/$', MemberPrograms.as_view(), name='program'),
9
]
 
 
 
 
 
 
4
 
 
 
 
 
1
class MemberPrograms(APIView):
2
    def get(self, request):
3
        programs = MemberProgram.objects.all().values()
4
        return JsonResponse(list(programs), safe=False)
 
 
测试:
            

现在接口已经实现了,但是我们要对这个接口增加权限控制,只允许vip,svip,admin用户访问,代码实现:
    方法一:
    上一章我们实现了自定义认证的中间件,现在可以利用起来,修改如下:
 
 
 
 
25
 
 
 
 
 
1
class MyAuthentication(BaseAuthentication):
2
    def authenticate(self, request):
3
        name = request._request.GET.get('username')
4
        print(name)
5
        return (name, None)
6

7

8
class MemberPrograms(APIView):
9
    authentication_classes = [MyAuthentication, ]
10

11
    def get(self, request):
12
        if not request.user:            # 没有用户身份,不允许访问
13
            ret = {'code': 1002, 'error': '权限被拒'}
14
            return JsonResponse(ret)
15
        username = request.user
16
        try:
17
            group_name = User.objects.get(username=username).group.group_name  
18
        except User.DoesNotExist:            # 用户身份不存在,返回错误信息
19
            ret = {'code': 1003, 'error': '用户不存在'}
20
            return JsonResponse(ret)
21
        if group_name == 'usual':           # 是普通用户,没有权限
22
            ret = {'code': 1002, 'error': '权限被拒'}
23
            return JsonResponse(ret)             
24
        programs = MemberProgram.objects.all().values()    # 用户权限满足条件 返回接口信息
25
        return JsonResponse(list(programs), safe=False)
 
 
测试:
              

               

上面实现了接口对用户权限的控制,实际项目代码不会这么简单,需要通过token进行判断,这里只是简单实现
方法二:
    利用restframework的permission组件实现:
 
 
 
x
 
 
 
 
 
1
from rest_framework.authentication import BaseAuthentication
2
from rest_framework.permissions import BasePermission
3
from rest_framework.exceptions import PermissionDenied
4

5
lass MyAuthentication(BaseAuthentication):
6
    def authenticate(self, request):
7
        name = request._request.GET.get('username')
8
        print(name)
9
        return (name, None)
10

11

12
class MyPermission(BasePermission):
13
    def has_permission(self, request, view):
14
        if not request.user:
15
            raise PermissionDenied('权限被拒')
16
        username = request.user
17
        try:
18
            group_name = User.objects.get(username=username).group.group_name
19
        except User.DoesNotExist:
20
            raise PermissionDenied('用户不存在')
21
        if group_name == 'usual':
22
            raise PermissionDenied('权限被拒')
23
        return True
24

25

26
class MemberPrograms(APIView):
27
    authentication_classes = [MyAuthentication, ]
28
    permission_classes = [MyPermission, ]
29

30
    def get(self, request):
31
        programs = MemberProgram.objects.all().values()
32
        return JsonResponse(list(programs), safe=False)
 
 
     上面的例子中我们都是将认证类和权限类注册在了对应的view视图中,
      其实要是项目中多数视图需要进行以上验证,那就可将自定义的认证类和权限类放在一个单独的文件中,然后注册到seeting.py中 :
  
          

在seeting.py中添加下面内容:
            

源码分析:
              

    1.请求的封装,将原先的request封装到restframework的APIview中,丰富了request内容,包含了authenticators等
    2. initial() 初始化
 
 
 
x
 
 
 
 
 
1
    def initial(self, request, *args, **kwargs):
2
        """
3
        Runs anything that needs to occur prior to calling the method handler.
4
        """
5
        self.format_kwarg = self.get_format_suffix(**kwargs)
6

7
        # Perform content negotiation and store the accepted info on the request
8
        neg = self.perform_content_negotiation(request)
9
        request.accepted_renderer, request.accepted_media_type = neg
10

11
        # Determine the API version, if versioning is in use.
12
        version, scheme = self.determine_version(request, *args, **kwargs)
13
        request.version, request.versioning_scheme = version, scheme
14

15
        # Ensure that the incoming request is permitted
16
        
17
        # 身份验证
18
        self.perform_authentication(request)
19
        # 权限验证
20
        self.check_permissions(request)
21
        self.check_throttles(request)
 
 
           调用了self.check_permissions(request)
 
 
 
x
 
 
 
 
 
1
    def check_permissions(self, request):
2
        """
3
        Check if the request should be permitted.
4
        Raises an appropriate exception if the request is not permitted.
5
        """
6
        for permission in self.get_permissions():    # 1
7
            if not permission.has_permission(request, self):  # 2
8
                self.permission_denied(    # 3
9
                    request, message=getattr(permission, 'message', None)
10
                )
 
 
    第一步: self.get_permissions:
 
 
 
x
 
 
 
 
 
1
    def get_permissions(self):
2
        """
3
        Instantiates and returns the list of permissions that this view requires.
4
        """
5
        return [permission() for permission in self.permission_classes]
6
    
7
    
8
self.permission_classes 就是我们定义的permissions,默认是从seeting.py配置文件中找,如果我们的view中制定了这一项,就使用view中的permission,而不用配置文件中的    
9
permission_classes = api_settings.DEFAULT_PERMISSION_CLASSES   
 
 
          第二步:permission.has_permission
          此时的permission就是定义的permission类,既然调用了has_permission方法,那我们的permission类就必须实现这个方法,这个方法中用来实现我们的权限校验逻辑
          源码判断这个函数,if not,说明如果has_permission函数的返回值不是True,就到第三步,否则集序循环下一个permission
          
          第三步:self.permission_denied
          可以看到这个方法需要两个参数,一个是request,一个是message=getattr(permission, 'message', None),getattr()从permission中找message,没找到就设为Node
 
 
 
x
 
 
 
 
 
1
    def permission_denied(self, request, message=None):
2
        """
3
        If request is not permitted, determine what kind of exception to raise.
4
        """
5
        if request.authenticators and not request.successful_authenticator:
6
            raise exceptions.NotAuthenticated()
7
        raise exceptions.PermissionDenied(detail=message)
 
 
          permission_denied最终抛出了一个异常exceptions.PermissionDenied,这个异常接受了message,而它实际就是我们异常的提示语,所以,可以修改上面自定义的MyPermission类,不需要我们手动抛出异常,只要return False即可:
class MyPermission(BasePermission):

message = '需要会员用户才能访问'

def has_permission(self, request, view):
if not request.user:
return False
username = request.user
try:
group_name = User.objects.get(username=username).group.group_name
except User.DoesNotExist:
return False
if group_name == 'usual':
return False
return True

 
 
 
x
 
 
 
 
 
1
class MyPermission(BasePermission):
2
    
3
    message = '需要会员用户才能访问'
4
    
5
    def has_permission(self, request, view):
6
        if not request.user:
7
            return False
8
        username = request.user
9
        try:
10
            group_name = User.objects.get(username=username).group.group_name
11
        except User.DoesNotExist:
12
            return False
13
        if group_name == 'usual':
14
            return False
15
        return True
 
 
        测试:
            

            
 

从FBV到CBV三(权限)的更多相关文章

  1. 一、虚拟环境.二、路由配置主页与404.三、2.x路由分发.四、伪静态.五、request对象.六、FBV与CBV.七、文件上传.

    一.虚拟环境 ''' 解决版本共存 1. 用pycharm选择File点击NewProject然后选择virtualenv创建一个纯净环境 2. 打开下载的目录将venv文件夹下的所有文件(纯净的环境 ...

  2. python 视图 (FBV、CBV ) 、Request 和Response对象 、路由系统

    一.FBV和CBV1.基于函数的view,就叫FBV(Function Based View) 示例: def add_book(request): pub_obj=models.Publisher. ...

  3. django请求生命周期,FBV和CBV,ORM拾遗,Git

    一.django 请求生命周期 流程图: 1. 当用户在浏览器中输入url时,浏览器会生成请求头和请求体发给服务端请求头和请求体中会包含浏览器的动作(action),这个动作通常为get或者post, ...

  4. Django之FBV与CBV

    一.FBV与CBV FBV(function based views),即基于函数的视图:CBV(class based views),即基于类的视图,也是基于对象的视图.当看到这个解释时,我是很萌的 ...

  5. python 全栈开发,Day84(django请求生命周期,FBV和CBV,ORM拾遗,Git)

    一.django 请求生命周期 流程图: 1. 当用户在浏览器中输入url时,浏览器会生成请求头和请求体发给服务端请求头和请求体中会包含浏览器的动作(action),这个动作通常为get或者post, ...

  6. django基础 -- 4. 模板语言 过滤器 模板继承 FBV 和CBV 装饰器 组件

    一.语法 两种特殊符号(语法): {{ }}和 {% %} 变量相关的用{{}},逻辑相关的用{%%}. 二.变量 1. 可直接用  {{ 变量名 }} (可调用字符串, 数字 ,列表,字典,对象等) ...

  7. Django FBV和CBV -

    一.FBV和CBV 在Python菜鸟之路:Django 路由.模板.Model(ORM)一节中,已经介绍了几种路由的写法及对应关系,那种写法可以称之为FBV: function base view ...

  8. django基础之FBV与CBV,ajax序列化补充,Form表单

    目录: FBV与CBV ajax序列化补充 Form表单(一) 一.FBV与CBV 1.什么是FBV.CBV? django书写view时,支持两种格式写法,FBV(function bases vi ...

  9. Python菜鸟之路:Django 路由补充1:FBV和CBV - 补充2:url默认参数

    一.FBV和CBV 在Python菜鸟之路:Django 路由.模板.Model(ORM)一节中,已经介绍了几种路由的写法及对应关系,那种写法可以称之为FBV: function base view ...

随机推荐

  1. Centos7 Devstack [Rocky] 重启后无法联网

    部署devstack-rocky版本后网络,可以 Ping 通自己的 IP,但 Ping 不同网关,ping不通同网段主机,查看网卡和ovs信息如下 解决 第一步 按造网上教程,修改br-ex,ens ...

  2. Ceph 客户端的 RPM 包升级问题

    问题 最近想把一个现有的 Ceph 客户端升级为最新的 M 版: [root@overcloud-ovscompute-0 ~]# rpm -qa | grep ceph puppet-ceph-2. ...

  3. Nginx OCSP

    #开启 vim  /path/to/path/conf/nginx.conf ..... events{ ...... 省略..... } http { ..... server{ listen 44 ...

  4. http常见状态码分析

    200:这个是最常见的http状态码,表示服务器已经成功接受请求,并将返回客户端所请求的最终结果 301:客户端请求的网页已经永久移动到新的位置,当链接发生变化时,返回301代码告诉客户端链接的变化, ...

  5. 06 vue router(一)

    一.vue route是什么? Vue Router是vue.js官方的路由管理器.主要有以下几种功能 1.路由和视图表的配置.(已明白) 2.模块化和基于组件的路由配置.(已明白) 3.路由参数.查 ...

  6. python-Web-django-钩子验证

    全局钩子验证: ‘’’ 打包前端input,views数据处理,链接moduls数据库,用来验证 ’’’ Views: Form=UserForm(request.POST)实例化对象 Form.cl ...

  7. 【HANA系列】SAP HANA SQL计算某日期是当月的第几天

    公众号:SAP Technical 本文作者:matinal 原文出处:http://www.cnblogs.com/SAPmatinal/ 原文链接:[HANA系列]SAP HANA SQL计算某日 ...

  8. MATLAB实现OTSU

    目录 1.OTSU算法原理简述: 2.MATLAB实现代码 @ 1.OTSU算法原理简述: 最大类间方差是由日本学者大津(Nobuyuki Otsu)于1979年提出,是一种自适应的阈值确定方法.算法 ...

  9. "a++" 与 "++a" 的区别-演示

    两种表示方法经常容易混淆, 在这里将利用演示程序来揭示两者之间的区别, 演示代码如下 int main() { ; cout << "a=1 " << &q ...

  10. Azure Blob 存储简介

    Azure Blob 存储是 Microsoft 提供的适用于云的对象存储解决方案. Blob 存储最适合存储巨量的非结构化数据. 非结构化数据是不遵循特定数据模型或定义(如文本或二进制数据)的数据. ...