django restframework框架三 权限

@(python之路)[django restframework框架二 权限]
django restframework框架二 权限

权限组件

我们一般将权限级别放到数据库中,这样也方便管理。
app01.urls.py

from django.conf.urls import url
from app01 import views
urlpatterns = [
    url(r'salary/$', views.SalaryView.as_view()),
]

model.py

from django.db import models
class UserInfo(models.Model):
    username = models.CharField(max_length=32)
    password = models.CharField(max_length=64)
    user_type_choices = (
        (1,"员工"),
        (2,"主管"),
    )
    user_type = models.IntegerField(choices=user_type_choices,default=1)

我们写两个视图,如果权限大于0,就允许访问;
如果权限大于一在可以访问这个视图;

from rest_framework.views import APIView
from django.shortcuts import render,HttpResponse
from django.http import JsonResponse

class MyPermission(object):
    def has_permission(self,request,view):
        return True

class SalaryView(APIView):
    permission_classes = [MyPermission,]
    def get(self,request,*args,**kwargs):
        self.dispatch
        return HttpResponse("get from SalaryView")
# usertype>1
class UserView(APIView):
    permission_classes = [MyPermission,]
    def get(self,request,*args,**kwargs):
        return HttpResponse("get from UserView")

因为我们的 def has_permission(self,request,view):返回的时True。都有查看权限。如果返回的False的话,那么所有人都不能访问。
我们可以在has_permission中拿到用户相关的权限.
根据用户权限,具体做判断,根据权限不同,做不同的操作。

from rest_framework.permissions import BasePermission
class UserPermission(BasePermission):
    def has_permission(self,request,view):
        user_type_id = request.auth.user.user_type
        if user_type_id > 0:
            return True
        return False

class ManagerPermission(BasePermission):
    def has_permission(self,request,view):
        user_type_id = request.auth.user.user_type
        if user_type_id > 1:
            return True
        return False

 一般我们的权限都是单独写出来的,一些基础的权限会放在全局。单独放一个文件就好。记得下视图使用的时候要导入的。
补充:我们把要加权限的类写法如下

class UserView(APIView):

    permission_classes = [UserPermission,]
    def get(self,request,*args,**kwargs):
        self.dispatch
        print(request.user)
        print(request.auth)
        return HttpResponse('user.get')
    def post(self,request,*args,**kwargs):
        return HttpResponse('user.post')
class SalaryView(APIView):
    permission_classes = [UserPermission,ManagerPermission, ]
    def get(self,request,*args,**kwargs):
        return HttpResponse('...')

源码分析

 我们还是从def dispatch()中的self.initial(request, *args, **kwargs)中入手
1

def initial(self, request, *args, **kwargs):
    self.format_kwarg = self.get_format_suffix(**kwargs)
    neg = self.perform_content_negotiation(request)
    
    request.accepted_renderer, request.accepted_media_type = neg

    # 版本处理
    version, scheme = self.determine_version(request, *args, **kwargs)
    request.version, request.versioning_scheme = version, scheme
    # 处理认证
    self.perform_authentication(request)
    # 这里就是权限
    self.check_permissions(request)
    self.check_throttles(request)

2
 我们看一下self.check_permissions(request)做了什么;

def check_permissions(self, request):
	# 循环每一个权限类实例化之后对象[per1,per2]
   for permission in self.get_permissions():
       # 当permission=False的时候,才会执行代码中的
       if not permission.has_permission(request, self):
           self.permission_denied(
               request, message=getattr(permission, 'message', None)
           )


这里我么研究一下permission_denied

def permission_denied(self, request, message=None):
    if request.authenticators and not request.successful_authenticator:
        raise exceptions.NotAuthenticated()
    raise exceptions.PermissionDenied(detail=message)

抛出异常,所以我们确定当permission=False时没有权限的,反之有权限;

3
 注意:self.get_permissions()

def get_permissions(self):
    return [permission() for permission in self.permission_classes]

 有种似曾相识的感觉。

class APIView(View):

    renderer_classes = api_settings.DEFAULT_RENDERER_CLASSES
    parser_classes = api_settings.DEFAULT_PARSER_CLASSES
    authentication_classes = api_settings.DEFAULT_AUTHENTICATION_CLASSES
    throttle_classes = api_settings.DEFAULT_THROTTLE_CLASSES
    
    permission_classes = api_settings.DEFAULT_PERMISSION_CLASSES
    
    content_negotiation_class = api_settings.DEFAULT_CONTENT_NEGOTIATION_CLASS
    metadata_class = api_settings.DEFAULT_METADATA_CLASS
    versioning_class = api_settings.DEFAULT_VERSIONING_CLASS

permission_classes = api_settings.DEFAULT_PERMISSION_CLASSES原理都是一样的。

posted @ 2018-06-01 17:22  zz小公子  阅读(164)  评论(0编辑  收藏  举报