20. drf权限管理

示例一: 登录了才能访问视图

from .serializers import UserSerializer
from rest_framework import viewsets
from django.contrib.auth import get_user_model
from django_filters.rest_framework import DjangoFilterBackend
from rest_framework.authentication import SessionAuthentication
from rest_framework.permissions import IsAuthenticated
User = get_user_model()

from .filters import UserFilter
class UserViewSet(viewsets.ReadOnlyModelViewSet):
    """
    retrieve:
        返回一个实例,当前也就是返回一个用户信息
    list:
        返回用户列表
    """
    queryset = User.objects.all()
    serializer_class = UserSerializer
    # 使用django_filters 进行搜索
    filter_backends = (DjangoFilterBackend,)
    # 使用搜索模型,还需要指定搜索模型
    filter_class=UserFilter
    # 表示只有登录了,才能访问当前视图
    permission_classes = (IsAuthenticated,) 

在这里插入图片描述

示例二:DRF认证(登录页面)

DRF也提供了一套认证,是基于session。它的配置非常简单,可以提供登录页面。

from django.conf.urls import url
....
urlpatterns = [
   url(r"^",include(route.urls)),    
   url(r'^api-auth', include("rest_framework.urls", namespace="rest_framework")),
   url(r"^docs/",include_docs_urls("运维平台接口文档")),

在这里插入图片描述
点击登录后,就可以正常访问页面
在这里插入图片描述

模型权限原理

除了之前讲解的,是否登录才有权限,还有其他的权限控制。例如是否是管理员,是否是安全的操作(get之类)才有权限。如下图。
在这里插入图片描述

模型权限 原理

class DjangoModelPermissions(BasePermission):
	权限映射,可以看到如果
    perms_map = {
        'GET': [],
        'OPTIONS': [],
        'HEAD': [],
        'POST': ['%(app_label)s.add_%(model_name)s'],
        'PUT': ['%(app_label)s.change_%(model_name)s'],
        'PATCH': ['%(app_label)s.change_%(model_name)s'],
        'DELETE': ['%(app_label)s.delete_%(model_name)s'],
    }

    authenticated_users_only = True

    def get_required_permissions(self, method, model_cls):
        """
        Given a model and an HTTP method, return the list of permission
        codes that the user is required to have.
        """
        kwargs = {
            'app_label': model_cls._meta.app_label,
            'model_name': model_cls._meta.model_name
        }

        if method not in self.perms_map:
            raise exceptions.MethodNotAllowed(method)

        return [perm % kwargs for perm in self.perms_map[method]]

    def _queryset(self, view):
        assert hasattr(view, 'get_queryset') \
            or getattr(view, 'queryset', None) is not None, (
            'Cannot apply {} on a view that does not set '
            '`.queryset` or have a `.get_queryset()` method.'
        ).format(self.__class__.__name__)

        if hasattr(view, 'get_queryset'):
            queryset = view.get_queryset()
            assert queryset is not None, (
                '{}.get_queryset() returned None'.format(view.__class__.__name__)
            )
            return queryset
        return view.queryset

    def has_permission(self, request, view):
        # Workaround to ensure DjangoModelPermissions are not applied
        # to the root view when using DefaultRouter.
        if getattr(view, '_ignore_model_permissions', False):
            return True

        if not request.user or (
           not request.user.is_authenticated and self.authenticated_users_only):
            return False

        queryset = self._queryset(view)
        perms = self.get_required_permissions(request.method, queryset.model)

        return request.user.has_perms(perms)

定义了一个映射,不同的请求需要不同的权限。

perms_map = {
    'GET': [],
    'OPTIONS': [],
    'HEAD': [],
    'POST': ['%(app_label)s.add_%(model_name)s'],
    'PUT': ['%(app_label)s.change_%(model_name)s'],
    'PATCH': ['%(app_label)s.change_%(model_name)s'],
    'DELETE': ['%(app_label)s.delete_%(model_name)s'],
}

用户想对这个模型有post操作。就必须要有给app_label 添加codename的权限才能处理。(对于get是没有做任何限制)对应如下图:
在这里插入图片描述
在这里插入图片描述

在这里插入图片描述
这张图可以看到它必须要有模型model_cls,也就是queryset
在这里插入图片描述
如果没有它,肯定就没有模型权限。

然后定义了包含可以使用的方法,如果不在映射中,则抛出异常:方法不存在。

示例: django模型权限(全局)

创建普通用户

>>> from django.contrib.auth.models import User
>>> User.objects.create_user('zhangsan','zhangsam@mail.com','123456')
<User: zhangsan>

全局设置:

# 全局生效。所有视图都需要获得对应权限,才能访问。
# 优点:不用每个视图写。  缺点:全局生效,没有写queryset或者没有获得对应权限就出错。解决方法,可以在视图中再写,表示不用全局,用自己的
'DEFAULT_PERMISSION_CLASSES': [
	# 貌似写法有问题
    #'django.filter.rest_framework.DjangoModelPermissions',
    # 全局
    # 'rest_framework.permissions.DjangoModelPermissions',
],

视图不想用全局的,可以覆盖重写(不做演示,举例而已)
在这里插入图片描述

此时以普通用户登录

可看到此时只有get权限(参照之前django模型权限图片,可以看到get是空,表示没有限制),其他功能都没有出来了
在这里插入图片描述

添加 添加制造商权限

mysql> select * from auth_permission;
+----+---------------------------+-----------------+----------------------+
| id | name                      | content_type_id | codename             |
+----+---------------------------+-----------------+----------------------+
....
| 37 | Can add manufacturer      |              10 | add_manufacturer     |
..
 39 | Can delete manufacturer   |              10 | delete_manufacturer  |
....
>>> from django.contrib.auth.models import Permission
>>> from django.contrib.auth.models import User
>>> u = User.objects.get(username="zhangsan")
>>> p=Permission.objects.get(pk=37)
>>> p
<Permission: manufacturer | manufacturer | Can add manufacturer>
>>> u.user_permissions.set([p])
>>> u.user_permissions.all()
<QuerySet [<Permission: manufacturer | manufacturer | Can add manufacturer>]>

此时这个页面就出来了 post功能
在这里插入图片描述
再添加delete

>>> p=Permission.objects.get(pk=39)
>>> u.user_permissions.add(p)
>>> u.user_permissions.all()
<QuerySet [<Permission: manufacturer | manufacturer | Can add manufacturer>, <Permission: manufacturer | manufacturer | Can delete manufacturer>]>

在这里插入图片描述

自定义(覆盖)django模型权限

例如重写get权限
默认的django模型权限

perms_map = {
    'GET': [],
    'OPTIONS': [],
    'HEAD': [],
    'POST': ['%(app_label)s.add_%(model_name)s'],
    'PUT': ['%(app_label)s.change_%(model_name)s'],
    'PATCH': ['%(app_label)s.change_%(model_name)s'],
    'DELETE': ['%(app_label)s.delete_%(model_name)s'],
}

如果不满足,可以覆盖它

在这里插入图片描述

需求:不是所有视图的get请求都没有限制。可对某些视图做get限制。这些视图需要满足权限设置才能得到get请求(访问)

users/view.py
auth.view_user (app_label.codename )
在这里插入图片描述

mysql> select * from auth_permission where codname='view_user';
+----+---------------------------+-----------------+----------------------+
| id | name                      | content_type_id | codename             |
+----+---------------------------+-----------------+----------------------+
| 16 | Can view user             |               4 | view_user            |
mysql> select * from django_content_type where app_label = 'auth';
+----+-----------+------------+
| id | app_label | model      |
+----+-----------+------------+
|  3 | auth      | group      |
|  2 | auth      | permission |
|  4 | auth      | user       |
+----+-----------+------------+
3 rows in set (0.00 sec)

原有基础上,增加了权限控制
在这里插入图片描述
全局配置文件启用自定义的权限模型
在这里插入图片描述
在这里插入图片描述
get_custom_perms 自定义的,目的是将视图中设置的get权限设置添加进来。

在这里插入图片描述
效果
在这里插入图片描述
server 也做测试。
注意这个名字要对应上 app_lables.view_model
在这里插入图片描述

在这里插入图片描述

加权限
在这里插入图片描述

在这里插入图片描述
再访问,此时就有权限
在这里插入图片描述

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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

数哥

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值