Django框架(二十)-- Django rest_framework-权限组件

一、权限组件的使用

# 用户信息表
class UserInfo(models.Model):
    name = models.CharField(max_length=32)
    # 写choice
    user_choice=((0,‘普通用户‘),(1,‘会员‘),(2,‘超级用户‘))
    # 指定choice,可以快速的通过数字,取出文字
    user_type=models.IntegerField(choices=user_choice,default=0)
    pwd = models.CharField(max_length=32)

# 用户token
class UserToken(models.Model):
    token = models.CharField(max_length=64)
    user = models.OneToOneField(to=UserInfo)

1、使用语法

from rest_framework.permissions import BasePermission

# 写一个权限类
class UserPermission(BasePermission):
    # 重写没有权限时的数据
    message = ‘您没有权限‘
    # 重写has_permission()方法,传入三个参数
    # 第一个是对象自身(自动传);第二个是request对象;第三个是
    def has_permission(self, request, view):
        # 只要认证通过,就会把当前用户对象放到request中
        user_type = request.user.user_type
        # get_字段名_display() 可以获取choice数字对应的具体值
        # user_type_name = request.user.get_user_type_display()
        # print(user_type_name)
        if user_type == 2:
            return True
        return Fals
class Book(APIView):
    # 用户认证
    authentication_classes = [UserAuth.UserAuth, ]
    # 权限判断
    permission_classes = [MyPerm.UserPermission, ]

    def get(self, request, *args, **kwargs):
        response = {‘status‘: 100, ‘msg‘: ‘查询成功‘}
        ret = models.Book.objects.all()
        ser = MySerializer.BookSerializer(instance=ret, many=True)
        response[‘data‘] = ser.data
        return JsonResponse(response, safe=False)

2、全局使用、局部使用、局部禁用权限

(1)全局使用

  • 在settings文件中配置,配置完以后,就无需在视图类中写,已经是所有视图类都需要权限判断
  • 必须为REST_FRAMEWORK,key值必须为DEFAULT_AUTHENTICATION_CLASSES
REST_FRAMEWORK={
    ‘DEFAULT_PERMISSION_CLASSES‘:[‘app01.MyPerm.UserPermission‘,],
}

(2)局部使用

在需要使用的视图类中写,只对当前视图类起认证作用,重新定义permission_classes

class Book(APIView):
    # # 该方法是局部使用认证
    authentication_classes = [UserAuth.UserAuth, ]
    # 该方法是局部使用权限
    permission_classes = [MyPerm.UserPermission, ]

    def get(self, request, *args, **kwargs):
        response = {‘status‘: 100, ‘msg‘: ‘查询成功‘}
        ret = models.Book.objects.all()
        ser = MySerializer.BookSerializer(instance=ret, many=True)
        response[‘data‘] = ser.data
        return JsonResponse(response, safe=False)

(3)局部禁用

在配置过全局权限判断以后,有些视图类不需要判断权限,可以局部禁用权限证,只需将permission_classes定义为空列表即可。

class Book(APIView):
    # # 该方法是局部使用认证
    authentication_classes = [UserAuth.UserAuth, ]
    # 该方法是局部禁用权限
    permission_classes = []

    def get(self, request, *args, **kwargs):
        response = {‘status‘: 100, ‘msg‘: ‘查询成功‘}
        ret = models.Book.objects.all()
        ser = MySerializer.BookSerializer(instance=ret, many=True)
        response[‘data‘] = ser.data
        return JsonResponse(response, safe=False)

二、源码分析

as_view ----------> view -------------> dispatch -------> Request包装新的request ------> 认证、权限、频率 --------> 根据请求方式分发到不同的方法

1、Book中没有as_view

2、APIView的as_view

class APIView(View):

    @classmethod
    # cls 是 Book类
    def as_view(cls, **initkwargs):

        # view = super(APIView, Book).as_view(**initkwargs)
        view = super(APIView, cls).as_view(**initkwargs)
        view.cls = cls
        view.initkwargs = initkwargs

        # Note: session based authentication is explicitly CSRF validated,
        # all other authentication is CSRF exempt.
        return csrf_exempt(view)

3、view = super(APIView, cls).as_view(**initkwargs) ---------------------> View中的as_view

class View(object):

    @classonlymethod
    # cls====> Book
    def as_view(cls, **initkwargs):

        def view(request, *args, **kwargs):
            # 实例化产生一个book对象
            self = cls(**initkwargs)
            if hasattr(self, ‘get‘) and not hasattr(self, ‘head‘):
                self.head = self.get
            self.request = request
            self.args = args
            self.kwargs = kwargs
            # 调dispatch方法
            return self.dispatch(request, *args, **kwargs)
        view.view_class = cls
        view.view_initkwargs = initkwargs

        # take name and docstring from class
        update_wrapper(view, cls, updated=())

        # and possible attributes set by decorators
        # like csrf_exempt from dispatch
        update_wrapper(view, cls.dispatch, assigned=())
        return view

4、return self.dispatch(request, *args, **kwargs) ----------------> dispatch

self====> Book对象,一层层找dispatch

APIView中找到dispatch

class APIView(View):

    def dispatch(self, request, *args, **kwargs):

        self.args = args
        self.kwargs = kwargs

        # (a)初始化request,就是通过Request类来包装原生request,得到包装后的request
        request = self.initialize_request(request, *args, **kwargs)
        # 从现在开始request就是包装后的request
        self.request = request
        self.headers = self.default_response_headers  # deprecate?

        try:
            # (b) 认证、权限、频率
            self.initial(request, *args, **kwargs)

            # Get the appropriate handler method
            # http_method_names表示列表[‘get‘, ‘post‘, ‘put‘, ‘patch‘, ‘delete‘, ‘head‘, ‘options‘, ‘trace‘]
            if request.method.lower() in self.http_method_names:
                handler = getattr(self, request.method.lower(),
                                  self.http_method_not_allowed)
            else:
                handler = self.http_method_not_allowed

            response = handler(request, *args, **kwargs)

        except Exception as exc:
            response = self.handle_exception(exc)

        self.response = self.finalize_response(request, response, *args, **kwargs)
        return self.response
    

(a)request = self.initialize_request(request, *args, **kwargs) 包装 request

self 是Book对象

class APIView(View):
    # 默认的认证列表类
    authentication_classes = api_settings.DEFAULT_AUTHENTICATION_CLASSES
    def initialize_request(self, request, *args, **kwargs):
        """
        Returns the initial request object.
        """
        parser_context = self.get_parser_context(request)
        # (a-b)实例化初始化产生新的request对象
        return Request(
            request,
            parsers=self.get_parsers(),
            authenticators=self.get_authenticators(),  # 认证类实例化产生的对象的列表
            negotiator=self.get_content_negotiator(),
            parser_context=parser_context
        )
    def get_authenticators(self):
        """
        Instantiates and returns the list of authenticators that this view can use.
        """
        return [auth() for auth in self.authentication_classes]
(a------1)return Request( ··· ) ----------> Request类初始化
    def __init__(self, request, parsers=None, authenticators=None,
                 negotiator=None, parser_context=None):
        assert isinstance(request, HttpRequest), (
            ‘The `request` argument must be an instance of ‘
            ‘`django.http.HttpRequest`, not `{}.{}`.‘
            .format(request.__class__.__module__, request.__class__.__name__)
        )

        self._request = request
        self.parsers = parsers or ()
        self.authenticators = authenticators or ()
        self.negotiator = negotiator or self._default_negotiator()
        self.parser_context = parser_context
        self._data = Empty
        self._files = Empty
        self._full_data = Empty
        self._content_type = Empty
        self._stream = Empty

        if self.parser_context is None:
            self.parser_context = {}
        self.parser_context[‘request‘] = self
        self.parser_context[‘encoding‘] = request.encoding or settings.DEFAULT_CHARSET

        force_user = getattr(request, ‘_force_auth_user‘, None)
        force_token = getattr(request, ‘_force_auth_token‘, None)
        if force_user is not None or force_token is not None:
            forced_auth = ForcedAuthentication(force_user, force_token)
            self.authenticators = (forced_auth,)

(b)self.initial(request, *args, **kwargs) -----> 认证、权限、频率

    def initial(self, request, *args, **kwargs):
        """
        Runs anything that needs to occur prior to calling the method handler.
        """
        self.format_kwarg = self.get_format_suffix(**kwargs)

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

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

        # Ensure that the incoming request is permitted
        # (b------1) 认证
        self.perform_authentication(request)
        # (b------2)权限
        self.check_permissions(request)
        # 频率
        self.check_throttles(request)
(b------1) self.check_permissions(request) -------> 权限判断
    def check_permissions(self, request):
        """
        Check if the request should be permitted.
        Raises an appropriate exception if the request is not permitted.
        """
        # (b------1---------1) get_permissions 权限类对象组成的列表
        for permission in self.get_permissions():
            # 重写的就是这个has_permission()方法,判断当前用户是否有权限
            if not permission.has_permission(request, self):
                self.permission_denied(
                    request, message=getattr(permission, ‘message‘, None)
                )
(b------1---------1) self.get_permissions() -------> 获取权限类对象组成的列表
def get_permissions(self):
    """
    Instantiates and returns the list of permissions that this view requires.
    """
    return [permission() for permission in self.permission_classes]

原文地址:https://www.cnblogs.com/zhangbingsheng/p/10720971.html

时间: 2024-10-11 05:03:28

Django框架(二十)-- Django rest_framework-权限组件的相关文章

Django框架(十六)—— forms组件、局部钩子、全局钩子

forms组件.局部钩子.全局钩子 一.什么是forms组件 forms组件就是一个类,可以检测前端传来的数据,是否合法. 例如,前端传来的邮箱数据,判断邮件格式对不对,用户名中不能以什么开头,等等 二.forms组件的使用 1.使用语法 from django.shortcuts import render, HttpResponse from django import forms # 1.先写一个类,继承Form class MyForm(forms.Form): # 定义一个属性,可以用

Django框架(十四)-- forms组件、局部钩子、全局钩子

一.什么是forms组件 forms组件就是一个类,可以检测前端传来的数据,是否合法. 例如,前端传来的邮箱数据,判断邮件格式对不对,用户名中不能以什么开头,等等 二.forms组件的使用 1.使用语法 from django.shortcuts import render, HttpResponse from django import forms # 1.先写一个类,继承Form class MyForm(forms.Form): # 定义一个属性,可以用来校验字符串类型 # 限制最大长度是

Django框架(十九)—— 序列化组件(serializer)

目录 序列化组件 一.利用for循环来实现序列化(繁琐) 二.利用Django提供的序列化组件(不可控需要的字段) 三.利用drf提供的序列化组件 1.基于Serializer类实现序列化--基本语法 2.基于Serializer类实现序列化--高级语法 3.基于ModelSerializer类实现序列化 序列化组件 # 模型层 from django.db import models class Book(models.Model): nid = models.AutoField(primar

Django 框架篇(十): django自带的认证系统

Django自带的用户认证 我们在开发一个网站的时候,无可避免的需要设计实现网站的用户系统.此时我们需要实现包括用户注册.用户登录.用户认证.注销.修改密码等功能,这还真是个麻烦的事情呢. Django作为一个完美主义者的终极框架,当然也会想到用户的这些痛点.它内置了强大的用户认证系统--auth,它默认使用 auth_user 表来存储用户数据. 回到顶部 auth模块 from django.contrib import auth auth中提供了许多实用方法: authenticate()

微信小程序把玩(二十四)toast组件

原文:微信小程序把玩(二十四)toast组件 toast消息提示框,可用在提示一些信息,比如清楚缓存给用户一个友好的提示!或操作一些请求不想让用户有什么操作,toast也可以做到因为toast显示时其他操作是无效的 主要属性: wxml <!--点击button触发toast--> <button type="primary" bindtap="listenerButton">点击显示toast</button> <!--t

微信小程序把玩(二十八)image组件

原文:微信小程序把玩(二十八)image组件 image组件也是一个程序不可缺少的,可以这样说一个app中image组件随处可以看到,一般 image有两种加载方式第一种是网络图片第二种是本地图片资源,都用src属性去指定. 重点属性: 三种缩放模式 九种剪切方式 wxml <!--3中是缩放模式 scaleToFill 不保持纵横比缩放图片,使图片的宽高完全拉伸至填满image元素 aspectFit 保持纵横比缩放图片,使图片的长边能完全显示出来.也就是说,可以完整地将图片显示出来. asp

Django框架(十五)-- cookie和session组件

一.cookie 1.cookie的由来 HTTP协议是无状态的.无状态的意思是每次请求都是独立的,它的执行情况和结果与前面的请求和之后的请求都无直接关系,它不会受前面的请求响应情况直接影响,也不会直接影响后面的请求响应情况. 客户端和服务器在某次会话中产生的数据,那无状态的就以为这些数据不会被保留.会话中产生的数据又是我们需要保存的,也就是说要“保持状态”.因此Cookie就是在这样一个场景下诞生. 2.什么是cookie 存储在客户端浏览器上的键值对. 随着服务器端的响应发送给客户端浏览器.

django框架&lt;二&gt;

django框架:   Models 1.基本创建 Django提供了一个抽象层("Model")的构建和管理Web应用程序的数据. Django使用一种新的方式,即:关系对象映射(Object Relational Mapping,简称ORM). 每个模型是一个Python类,子类django.db.models.model 模型中的每个属性代表一个数据库字段. # DEMO class Student(models.Model): name = models.CharField(m

Django 框架篇: 一. Django介绍; 二. 安装; 三. 创建项目;

一. web框架:   框架,即framework,特指为解决一个开放性问题而设计的具有一定约束性的支撑结构,使用框架可以帮你快速开发特定的系统,简单地说,就是你用别人搭建好的舞台来做表演. 对于所有的Web应用,本质上其实就是一个socket服务端,用户的浏览器其实就是一个socket客户端. import socket def handle_request(client): buf = client.recv(1024) client.send("HTTP/1.1 200 OK\r\n\r\

Django 框架篇(九): Django中的Form 组件

Django中的Form组件,帮我们处理了 form表单中的校验, 和错误提示的处理: 主要功能: 生成页面可用的HTML标签 对用户提交的数据进行校验 保留上次输入内容 使用form组件实现注册功能 1.  定义一个类, 继承django中的 forms.Form 代码实例: from django import forms # 按照Django form组件的要求自己写一个类 class RegForm(forms.Form): name = forms.CharField(label="用