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

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,)

20. drf权限管理_django

示例二: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("运维平台接口文档")),

20. drf权限管理_搜索_02

点击登录后,就可以正常访问页面

20. drf权限管理_自定义_03

模型权限原理

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

20. drf权限管理_django_04

模型权限 原理

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是没有做任何限制)对应如下图:

20. drf权限管理_django_05

20. drf权限管理_搜索_06

20. drf权限管理_django_07

这张图可以看到它必须要有模型model_cls,也就是queryset

20. drf权限管理_搜索_08

如果没有它,肯定就没有模型权限。

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

示例: 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',
],

视图不想用全局的,可以覆盖重写(不做演示,举例而已)

20. drf权限管理_搜索_09

此时以普通用户登录

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

20. drf权限管理_搜索_10

添加 添加制造商权限

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功能

20. drf权限管理_搜索_11

再添加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>]>

20. drf权限管理_自定义_12

自定义(覆盖)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'],
}

如果不满足,可以覆盖它

20. drf权限管理_自定义_13

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

users/view.py

auth.view_user (app_label.codename )

20. drf权限管理_搜索_14

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)

原有基础上,增加了权限控制

20. drf权限管理_自定义_15

全局配置文件启用自定义的权限模型

20. drf权限管理_自定义_16

20. drf权限管理_搜索_17

get_custom_perms 自定义的,目的是将视图中设置的get权限设置添加进来。

20. drf权限管理_自定义_18

效果

20. drf权限管理_django_19

server 也做测试。

注意这个名字要对应上 app_lables.view_model

20. drf权限管理_自定义_20

20. drf权限管理_django_21

加权限

20. drf权限管理_django_22

20. drf权限管理_django_23

再访问,此时就有权限

20. drf权限管理_搜索_24