Django Rest_Framework之视图集和权限配置

一.问题

问题:下面这种情况如果将全部视图子类全部继承在一个视图类里面就会造成一个问题,有的是带参数的,有的不带参数,那么这种情况访问就会报错,如果写两个视图类的话里面就会有重复代码,这种情况就要使用下面的视图集来解决。
在这里插入图片描述

二.常用视图集ViewSet

继承自APIViewViewSetMixin,作用也与APIView基本类似,提供了身份认证、权限校验、流量管理等。

ViewSet主要通过继承ViewSetMixin来实现在调用as_view()时传入字典(如{‘get’:‘list’})的映射处理工作。

在ViewSet中,没有提供任何动作action方法,需要我们自己实现action方法。

示例:

class StudentViewSet(ViewSet):
	
	# 获取一条数据
    def get_one(self,request,pk):

        student_obj = Student.objects.get(pk=pk)
        serializers = StudemtModelSerializers(instance=student_obj)
        return Response(serializers.data)
    
    # 获取所有的数据
    def get_all(self,request):
        student_list = Student.objects.all()
        serializers = StudemtModelSerializers(instance=student_list,many=True)
        return Response(serializers.data)

url.py:

# 常用视图集
path('test_student1/',views.StudentViewSet.as_view({'get':'get_all'})),
re_path('test_student1/(?P<pk>\d+)/',views.StudentViewSet.as_view({'get':'get_one'})),

三.通用视图集GenericViewSet

使用ViewSet通常并不方便,因为list、retrieve、create、update、destory等方法都需要自己编写,而这些方法与前面讲过的Mixin扩展类提供的方法同名,所以我们可以通过继承Mixin扩展类来复用这些方法而无需自己编写。但是Mixin扩展类依赖与GenericAPIView,所以还需要继承GenericAPIView

GenericViewSet就帮助我们完成了这样的继承工作,继承自GenericAPIViewViewSetMixin,在实现了调用as_view()时传入字典(如{'get':'list'})的映射处理工作的同时,还提供了GenericAPIView提供的基础方法,可以直接搭配Mixin扩展类使用。

示例:

from rest_framework.generics import GenericAPIView

class StudentGenericAPIView(GenericAPIView):

    serializer_class = StudemtModelSerializers
    queryset = Student.objects.all()

    # 获取所有
    def list(self,request):
        serializer = self.get_serializer(instance=self.get_queryset(),many=True)
        return Response(serializer.data)

    # 获取一条
    def retrieve(self,request,pk):
        serializers = self.get_serializer(instance=self.get_object())
        return Response(serializers.data)

urls.py:

# 通用视图集
path('test_student2/', views.Student2GenericAPIView.as_view({'get':'list'})),
re_path('test_student2/(?P<pk>\d+)/', views.Student2GenericAPIView.as_view({'get': 'retrieve'})),

四.通用视图集和扩展视图类mixins

from rest_framework.mixins import CreateModelMixin,ListModelMixin,UpdateModelMixin,RetrieveModelMixin,DestroyModelMixin

CreateModelMixin:创建一条
ListModelMixin:获取所有
UpdateModelMixin:更新一条
RetrieveModelMixin:获取一条
DestroyModelMixin:删除一条

class Student3GenericAPIView(GenericViewSet,ListModelMixin,RetrieveModelMixin):
    serializer_class = StudemtModelSerializers
    queryset = Student.objects.all()

	
	# 获取前几条
    def get_top(self,request):
        serializers = self.get_serializer(instance=self.get_queryset()[0:2],many=True)
        return Response(serializers.data)

urls.py:

# 通用视图集和扩展视图类mixins
path('test_student3/', views.Student3GenericAPIView.as_view({'get': 'list'})),
path('test_student3/get_top/', views.Student3GenericAPIView.as_view({'get': 'get_top'})),
re_path('test_student3/(?P<pk>\d+)/', views.Student3GenericAPIView.as_view({'get': 'retrieve'})),

五.只读视图集ReadOnlyModelViewSet

继承自GenericViewSet,同时包括了ListModelMixin、RetrieveModelMixin。

示例:

from rest_framework.viewsets import ReadOnlyModelViewSet

class Student4GenericAPIView(ReadOnlyModelViewSet):
    
    serializer_class = StudemtModelSerializers
    queryset = Student.objects.all()

urls.py:

# 只读视图集
    path('test_student4/', views.Student4GenericAPIView.as_view({'get': 'list'})),
    re_path('test_student4/(?P<pk>\d+)/', views.Student4GenericAPIView.as_view({'get': 'retrieve'})),

六.模型视图集ModelViewSet

继承自GenericViewSet,同时包括了ListModelMixin、RetrieveModelMixin、CreateModelMixin、UpdateModelMixin、DestoryModelMixin。

示例:

from rest_framework.viewsets import ModelViewSet

class Student5GenericAPIView(ModelViewSet):

    serializer_class = StudemtModelSerializers
    queryset = Student.objects.all()

urls.py:

 # 模型视图集
    path('test_student4/', views.Student5GenericAPIView.as_view({'get': 'list','post':'create'})),
    re_path('test_student4/(?P<pk>\d+)/', views.Student5GenericAPIView.as_view({'get': 'retrieve','put':'update','delete':'destroy'})),

七.动作属性action

在视图集中,我们可以通过action对象属性来获取当前请求视图集时的action动作是哪个。
通过路由访问到当前方法中.可以看到本次的action就是请求的方法名。

from rest_framework.decorators import action


class Student6ViewSet(ViewSet):

    def get_one(self,request,pk):
        print(self.action)          #获取视图集方法名  get_one
        student_obj = Student.objects.get(pk=pk)
        serializers = StudemtModelSerializers(instance=student_obj)
        return Response(serializers.data)

    def get_all(self,request):
         #在视图集中 因为自定义视图方法的名字会各种各样 所以需要在视图中获取当前客户端请求的视图方法名则可以使用self.action属性来查看
        print(self.action)          #获取视图集方法名
        student_list = Student.objects.all()
        serializers = StudemtModelSerializers(instance=student_list,many=True)
        return Response(serializers.data)

八.使用action装饰器来简写路由

视图集中附加action的声明:

示例:

class Student7ViewSet(ViewSet):

    @action(methods=['get'],detail=True)
    def get_one(self,request,pk):
        print(self.action)          #获取视图集方法名
        student_obj = Student.objects.get(pk=pk)
        serializers = StudemtModelSerializers(instance=student_obj)
        return Response(serializers.data)

    @action(methods=['get'],detail=False)
    def get_all(self,request):
        print(self.action)          #获取视图集方法名
        student_list = Student.objects.all()
        serializers = StudemtModelSerializers(instance=student_list,many=True)
        return Response(serializers.data)

使用Routers来帮助我们快速实现路由信息。
REST framework提供了两个router

  • SimpleRouter
  • DefaultRouter

urls.py中:

# 基于action装饰器和路由类来生成路由,达到简写的目的
# 一共有两个:SimpleRouter DefaultRouter  作用:为视图集生成url路由   使用方式一模一样 效果也是一样
from rest_framework.routers import DefaultRouter,SimpleRouter

# 实例化路由类
route = DefaultRouter()

# 注册视图集 生成视图集对应的路由
# router.register('路由前缀','视图集类','可选参数:路由别名前缀') # 3个参数
route.register('student7',views.Student7ViewSet,'student7')

# 生成的路由
print(route.urls)

生成的格式:
students6/get_all   Student6APIViewSet.get_all
students6/<pk>/get_one   Student6APIViewSet.get_one 注意:获取单条数据pk值在前面

urlpatterns += route.urls

九.权限和认证

1.session认证Authentication
可以在配置文件settings.py中配置全局默认的认证方案:
认证方式:

  • session认证:SessionAuthentication
  • 基本认证:BaseAuthentication
# drf 使用的认证 与django的进行区分
# 后续的drf使用的认证可以加在下面这个字典中
REST_FRAMEWORK = {
    'DEFAULT_AUTHENTICATION_CLASSES': (
        'rest_framework.authentication.SessionAuthentication',  # session认证
        'rest_framework.authentication.BasicAuthentication',   # 基本认证
    )
}

2.权限Permissions

权限控制可以限制用户对于视图的访问和对于具体数据对象的访问。

  • 在执行视图的dispatch()方法前,会先进行视图访问权限的判断
  • 在通过get_object()获取具体对象时,会进行模型对象访问权限的判断

全局设置:

REST_FRAMEWORK = {
	# 表示通过认证的用户可访问
    'DEFAULT_PERMISSION_CLASSES': (
        'rest_framework.permissions.IsAuthenticated',
    )
}

如果未指明,则采用如下默认配置:

# 所有用户
'DEFAULT_PERMISSION_CLASSES': (
   'rest_framework.permissions.AllowAny',
)

提供的权限:

  • AllowAny 允许所有用户
  • IsAuthenticated 仅通过认证的用户
  • IsAdminUser 仅管理员用户
  • IsAuthenticatedOrReadOnly 已经登陆认证的用户可以对数据进行增删改操作,没有登陆认证的游客只能查看数据。

示例:

from rest_framework.response import Response
from student.serializers import StudentModelserializers
from rest_framework.permissions import AllowAny,IsAuthenticatedOrReadOnly,IsAuthenticated,IsAdminUser
from rest_framework.views import APIView
from student.models import Student
from rest_framework.authentication import SessionAuthentication,BaseAuthentication

class StudentPermission(APIView):

    authentication_classes = [SessionAuthentication]  # 经过session认证的用户
    permission_classes = [IsAuthenticated]            # 设置这个表示是通过认证的用户可以访问这个视图集

    def get(self,request):
        student_list = Student.objects.all()
        serializers = StudentModelserializers(instance=student_list,many=True)
        return Response(serializers.data)

3.自定义权限:
如需自定义权限,需继承rest_framework.permissions.BasePermission父类,并实现以下两个任何一个方法或全部

  • .has_permission(self, request, view)

    是否可以访问视图, view表示当前视图对象

  • .has_object_permission(self, request, view, obj)

    是否可以访问数据对象, view表示当前视图, obj为模型数据对象

示例:
判断当前视图集是否是StudentPermission对象。

# 自定义权限
from rest_framework.permissions import BasePermission
class CustomePermission(BasePermission):

    # 针对视图集
    def has_permission(self, request, view):
        if isinstance(view,StudentPermission):
            return False

    # 针对模型数据对象
    def has_object_permission(self, request, view, obj):
        pass


class StudentPermission(APIView):

    # 自定义权限认证
    permission_classes = [CustomePermission] 

    def get(self,request):
        student_list = Student.objects.all()
        serializers = StudentModelserializers(instance=student_list,many=True)
        return Response(serializers.data)

结果:
在这里插入图片描述

十.限流

可选限流类:

1) AnonRateThrottle

限制所有匿名未认证用户,使用IP区分用户。

使用DEFAULT_THROTTLE_RATES['anon'] 来设置频次

2)UserRateThrottle

限制认证用户,使用User id 来区分。

使用DEFAULT_THROTTLE_RATES['user'] 来设置频次

3)ScopedRateThrottle

限制用户对于每个视图的访问频次,使用ip或user id。

# 限流
    'DEFAULT_THROTTLE_CLASSES': (
        'rest_framework.throttling.AnonRateThrottle',  # 针对匿名用户
        'rest_framework.throttling.UserRateThrottle',  # 针对登录用户
        'rest_framework.throttling.ScopedRateThrottle',  # 针对自定义视图进行限流
    ),

    # 全局配置 针对整个项目中所有的视图进行限流
    #DEFAULT_THROTTLE_RATES` 可以使用 second, minute, hour 或day来指明周期。
    'DEFAULT_THROTTLE_RATES': {
            'anon': '5000/minute',        # 针对游客5000一分钟 限制访问所有的视图方法的评率为100一天
            'user': '3000/minute',         # 针对登录用户3000一分钟  限制访问所有的视图方法的评率为1000一天
            'students': '1000/minute'      # 针对视图限流1000一分钟
        },

示例:
from rest_framework.throttling import AnonRateThrottle,UserRateThrottle

自定义权限

from rest_framework.permissions import BasePermission

class StudentPermission(APIView):
   
    # 限流 针对已经登录的用户
    throttle_classes = [UserRateThrottle]
	
	# 针对视图集
	throttle_scope = 'students'


    def get(self,request):
        student_list = Student.objects.all()
        serializers = StudentModelserializers(instance=student_list,many=True)
        return Response(serializers.data)

在这里插入图片描述

猜你喜欢

转载自blog.csdn.net/qq_39253370/article/details/106543629