问题:下面这种情况如果将全部视图子类全部继承在一个视图类里面就会造成一个问题,有的是带参数的,有的不带参数,那么这种情况访问就会报错,如果写两个视图类的话里面就会有重复代码,这种情况就要使用下面的视图集来解决。
继承自APIView
与ViewSetMixin
,作用也与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\d+)/' ,views.StudentViewSet.as_view({'get':'get_one'})),
使用ViewSet通常并不方便,因为list、retrieve、create、update、destory等方法都需要自己编写,而这些方法与前面讲过的Mixin扩展类提供的方法同名,所以我们可以通过继承Mixin扩展类来复用这些方法而无需自己编写。但是Mixin扩展类依赖与GenericAPIView
,所以还需要继承GenericAPIView
。
GenericViewSet就帮助我们完成了这样的继承工作,继承自GenericAPIView
与ViewSetMixin
,在实现了调用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\d+)/' , views.Student2GenericAPIView.as_view({'get': 'retrieve'})),
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\d+)/' , views.Student3GenericAPIView.as_view({'get': 'retrieve'})),
继承自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\d+)/' , views.Student4GenericAPIView.as_view({'get': 'retrieve'})),
继承自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\d+)/' , views.Student5GenericAPIView.as_view({'get': 'retrieve','put':'update','delete':'destroy'})),
在视图集中,我们可以通过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的声明:
示例:
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
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中配置全局默认的认证方案:
认证方式:
# drf 使用的认证 与django的进行区分
# 后续的drf使用的认证可以加在下面这个字典中
REST_FRAMEWORK = {
'DEFAULT_AUTHENTICATION_CLASSES': (
'rest_framework.authentication.SessionAuthentication', # session认证
'rest_framework.authentication.BasicAuthentication', # 基本认证
)
}
2.权限Permissions
权限控制可以限制用户对于视图的访问和对于具体数据对象的访问。
全局设置:
REST_FRAMEWORK = {
# 表示通过认证的用户可访问
'DEFAULT_PERMISSION_CLASSES': (
'rest_framework.permissions.IsAuthenticated',
)
}
如果未指明,则采用如下默认配置:
# 所有用户
'DEFAULT_PERMISSION_CLASSES': (
'rest_framework.permissions.AllowAny',
)
提供的权限:
示例:
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)