一级类视图
APIView
from rest_framework.views import APIView
APIView
是REST framework提供的所有视图的基类,继承自Django的View
父类。
APIView
与View
的不同之处在于:
- 传入到视图方法中的是REST framework的
Request
对象,而不是Django的HttpRequeset
对象; - 视图方法可以返回REST framework的
Response
对象,视图会为响应数据设置(render)符合前端要求的格式; - 任何
APIException
异常都会被捕获到,并且处理成合适的响应信息; - 在进行dispatch()分发前,会对请求进行身份认证、权限检查、流量控制。
支持定义的属性:
- authentication_classes列表或元祖,身份认证类
- permissoin_classes列表或元祖,权限检查类
- throttle_classes列表或元祖,流量控制类
在APIView
中仍以常规的类视图定义方法来实现get() 、post() 或者其他请求方式的方法。
class Test(APIView):
"""
APIView演示
"""
def get(self,request):
test_obj = Test.objects.all()
ser = Test_Serializer(test_obj,many=True)
return Response(ser.data)
def post(self,request):
ser = Test_Serializer(data=request.data)
if ser.is_valid():
ser.save()
return Response({"code":200})
限流配制
对接口访问的频次进行限制,以减轻服务器压力
全局配制
# settings.py
REST_FRAMEWORK = {
'DEFAULT_THROTTLE_CLASSES': (
'rest_framework.throttling.AnonRateThrottle',
'rest_framework.throttling.UserRateThrottle'
),
'DEFAULT_THROTTLE_RATES': {
'anon': '2/m', # 匿名用户对应的节流次数
'user': '5/m' # 登录用户对应的节流次数
}
}
DEFAULT_THROTTLE_RATES
可以使用second
,minute
,hour
或day
来指明周期,也可以在具体视图中通过throttle_classess属性来配置
# 对需要限流的接口进行设置
from rest_framework.throttling import UserRateThrottle
class Test(APIView):
throttle_classes = (UserRateThrottle,)
def get(self,request):
pass
可选限流类
1) AnonRateThrottle限制所有匿名未认证用户,使用IP区分用户。
使用DEFAULT_THROTTLE_RATES['anon']
来设置频次
2)UserRateThrottle限制认证用户,使用user id 来区分。
使用DEFAULT_THROTTLE_RATES['user']
来这是频次
3)ScopedRateThrottle限制用户对于每个视图的访问频次,使用ip或user id。
二级视图
GenericAPIView
继承自APIVIew
,增加了对于列表视图和详情视图可能用到的通用支持方法。通常使用时,可搭配一个或多个Mixin扩展类。
使用GenericAPIView类一般需要实现queryset属性或者重写get_queryset方法
支持定义的属性:
- 列表视图与详情视图通用:
- queryset列表视图的查询集
- serializer_class视图使用的序列化器
- 列表视图使用:
- pagination_class分页控制类
- filter_backends过滤控制后端
- 详情页视图使用:
- lookup_field查询单一数据库对象时使用的条件字段,默认为’
pk
’ - lookup_url_kwarg查询单一数据时URL中的参数关键字名称,默认与look_field相同
- lookup_field查询单一数据库对象时使用的条件字段,默认为’
提供的方法:
-
列表视图与详情视图通用:
-
get_queryset(self)
返回视图使用的查询集,是列表视图与详情视图获取数据的基础,默认返回
queryset
属性,可以重写,例如:def get_queryset(self): user = self.request.user return user.accounts.all()
-
get_serializer_class(self)
返回序列化器类,默认返回
serializer_class
,可以重写,例如:def get_serializer_class(self): if self.request.user.is_staff: return FullAccountSerializer return BasicAccountSerializer
-
*get_serializer(self,_args, _kwargs)
返回序列化器对象,被其他视图或扩展类使用,如果我们在视图中想要获取序列化器对象,可以直接调用此方法。
注意,在提供序列化器对象的时候,REST framework会向对象的context属性补充三个数据:request、format、view,这三个数据对象可以在定义序列化器时使用。
-
-
详情视图使用:
-
**get_object(self)**返回详情视图所需的模型类数据对象,默认使用
lookup_field
参数来过滤queryset。 在试图中可以调用该方法获取详情信息的模型类对象。若详情访问的模型类对象不存在,会返回404。
该方法会默认使用APIView提供的check_object_permissions方法检查当前对象是否有权限被访问。
-
添加展示实现
class AdGeneric(GenericAPIView):
queryset = Ad.objects.all()
serializer_class = AdSer
def get(self,request):
ad = self.get_queryset()
ser = self.get_serializer(ad,many=True)
return Response(ser.data)
def post(self,request):
ser = self.get_serializer(data=request.data)
if ser.is_valid():
ser.save()
return Response({"code":200})
Mixin
ListModelMixin
列表视图扩展类,提供list(request, *args, **kwargs)
方法快速实现列表视图,返回200状态码。
该Mixin的list方法会对数据进行过滤和分页
from rest_framework.pagination import PageNumberPagination
from rest_framework.mixins import ListModelMixin
class PageClass(PageNumberPagination):
page_size = 1 # 每页展示数据条数
# 对Test表中的数据进行分页展示
class TestMixin(GenericAPIView,ListModelMixin):
queryset = Test.objects.all()
serializer_class = Test_Serializer
pagination_class = Pages
def get(self,request):
return self.list(request)
CreateModelMixin
创建视图扩展类,提供create(request, *args, **kwargs)
方法快速实现创建资源的视图,成功返回201状态码。
如果序列化器对前端发送的数据验证失败,返回400错误。
from rest_framework.mixins import CreateModelMixin
class TestMixin(GenericAPIView,CreateModelMixin):
queryset = Test.objects.all()
serializer_class = Test_Serializer
def post(self,request):
return self.create(request)
UpdateModelMixin
更新视图扩展类,提供update(request, *args, **kwargs)
方法,可以快速实现更新一个存在的数据对象。
同时也提供partial_update(request, *args, **kwargs)
方法,可以实现局部更新。
成功返回200,序列化器校验数据失败时,返回400错误。
#re_path('admodify/(?P<pk>\d+)/$',AdMixin.as_view())
from rest_framework.mixins import UpdateModelMixin
class TestMixin(GenericAPIView,UpdateModelMixin):
queryset = Test.objects.all()
serializer_class = Test_Serializer
def put(self,request,pk):
return self.update(request)
DestroyModelMixin
删除视图扩展类,提供destroy(request, *args, **kwargs)
方法,可以快速实现删除一个存在的数据对象。
成功返回204,不存在返回404。
from rest_framework.mixins import DestroyModelMixin,ListModelMixin
class TestMixin(GenericAPIView,DestroyModelMixin,ListModelMixin):
queryset = Test.objects.all()
serializer_class = Test_Serializer
def get(self,request):
return self.list(request)
def delete(self,request,pk):
return self.destroy(request)
RetrieveModelMixin
详情视图扩展类,提供retrieve(request, *args, **kwargs)
方法,可以快速实现返回一个存在的数据对象。
如果存在,返回200, 否则返回404。
from rest_framework.mixins import RetrieveModelMixin
class TestMixin(GenericAPIView,RetrieveModelMixin):
queryset = Test.objects.all()
serializer_class = Test_Serializer
def get(self,request,pk):
return self.retrieve(request)
子类视图
CreateAPIView
提供 post 方法
继承自: GenericAPIView、CreateModelMixin
class TestCreateView(CreateAPIView):
serializer_class = TestCreateSer
ListAPIView
提供 get 方法
继承自:GenericAPIView、ListModelMixin
class TeacherListView(ListAPIView):
queryset = Test.objects.all()
serializer_class = Test_Serializer
RetireveAPIView
提供 get 方法
继承自: GenericAPIView、RetrieveModelMixin
class GenericList(RetrieveAPIView):
queryset = Test.objects.all()
serializer_class = Test_Serializer
lookup_field='id' # 查询的字段
DestroyAPIView
提供 delete 方法
继承自:GenericAPIView、DestoryModelMixin
class GenericList(DestroyAPIView):
queryset = Test.objects.all()
serializer_class = Test_Serializer
lookup_field='id'
UpdateAPIView
提供 put 和 patch 方法
继承自:GenericAPIView、UpdateModelMixin
class TestUpdateView(UpdateAPIView):
lookup_field = 'pk'
queryset = Test.objects.all()
serializer_class = Test_Serializer
RetrieveUpdateAPIView
提供 get、put、patch方法
继承自: GenericAPIView、RetrieveModelMixin、UpdateModelMixin
class TestUpdateView(RetrieveUpdateAPIView):
lookup_field = 'pk'
queryset = Test.objects.all()
serializer_class = Test_Serializer
RetrieveUpdateDestoryAPIView
提供 get、put、patch、delete方法
继承自:GenericAPIView、RetrieveModelMixin、UpdateModelMixin、DestoryModelMixin
class TestUpdateView(RetrieveUpdateDestoryAPIView):
lookup_field = 'pk'
queryset = Test.objects.all()
serializer_class = Test_Serializer
视图集
视图集简单来说就是一群视图逻辑操作的功能合集,并可采用路由映射的方式进行功能选择,编写的内置逻辑方法不再是使用请求命名,而是使用功能来进行命名
视图集类不再实现 get、post 等方法,而是实现动作 action 如 list、create 等,视图集只在使用 as_view 方法的时候,才会将 action 动作与具体请求方式对应上
class CartRecordView(ViewSet):
def list(self,request):
record = CarRecord.objects.all()
ser = CarRecordSer(record,many=True)
return Response({'mes':ser.data})
def retrieve(self,request,id):
record = CarRecord.objects.filter(id=id).first()
ser = CarRecordSer(record)
return Response({'mes':ser.data})
def create(self,request):
record = CarRecordSer(data=request.data)
if record.is_valid():
record.save()
return Response('ok')
那么他的路由映射不是之前的直接 as_view,还要对应采取对应请求进行映射
ViewSet
继承自 APIView,作用也与 APIView 基本类似,提供了身份认证、权限校验、流量管理等
在 ViewSet 中,没有提供任何动作 action 方法,需要我们自己实现 action 方法
说白了,ViewSet 只是让我们可以在路由配置的地方可以进行请求映射,属于最基础的视图集基类
from rest_framework import viewsets
class UserViewSet(viewsets.ViewSet):
def list(self,request):
pass
def retrieve(self,request,id):
pass
def create(self,request):
pass
def update(self, request, id=None):
print('update')
def destroy(self, request, id=None):
print('destroy')
path('viewset/', views.ModelViewSet.as_view({'get': 'list', 'post': 'create'})),
path('viewset/<int:pk>/',views.ModelViewSet.as_view({'get':'retrieve','put':'update','destroy': 'destroy'}))
GenericViewSet
继承自 GenericAPIView,作用也与 GenericAPIView 类似,提供了 get_object、get_queryset 等方法便于列表视图与详情信息视图的开发
class CarViewSetM(GenericViewSet):
queryset = CarRecord.objects.all()
serializer_class = CarRecordSer
lookup_field='id'
def list(self,request):
record = self.get_queryset()
ser = self.get_serializer(record,many=True)
return Response({'mes':ser.data})
def retrieve(self,request,id):
record = self.get_queryset()
ser = CarRecordSer(record)
return Response({'mes':ser.data})
def create(self,request):
record = CarRecordSer(data=request.data)
if record.is_valid():
record.save()
return Response('ok')
def update(self,request):
instance = self.get_object()
serializer = self.get_serializer(instance=instance,data=request.data)
serializer.is_valid(raise_exception=True)
instance = serializer.save()
return instance
def destory(self,request):
record = self.get_queryset()
record.delete()
return Response('ok')
path('CarViewSetM/',views.CarViewSetM.as_view({'get':'list','post':'create'})),
path('varViewSetDetail/<int:id>',views.CarViewSetM.as_view({'get':'retrieve','put':'update','delete':'destory'}))
ModelViewSet
在 ModelViewSet 从类继承 GenericAPIView,并包括用于各种动作实现方式中,通过在各种混入类的行为混合,包含了**.list**、.retrieve、.create、.update、.partial_update、和**.destroy** 等方法,继承 ListModelMixin、RetrieveModelMixin、CreateModelMixin、UpdateModelMixin、DestroyModelMixin
需要至少提供 queryset 和 serializer_class 属性
class CarViewSetM(ModelViewSet):
queryset = CarRecord.objects.all()
serializer_class = CarRecordSer
lookup_field='id'
path('CarViewSetM/',views.CarViewSetM.as_view({'get':'list','post':'create'})),
path('varViewSetDetail/<int:id>',views.CarViewSetM.as_view({'get':'retrieve','put':'update','delete':'destory'}))
ReadOnlyModelViewSet
该 ReadOnlyModelViewSet* 班也继承 GenericAPIView*,但只是提供了读取数据**的操作,含有的 action 有 *list* 和 *retrieve*
需要至少提供 *queryset* 和 *serializer_class* 属性
class CarViewSetM(ReadOnlyModelViewSet):
queryset = CarRecord.objects.all()
serializer_class = CarRecordSer
lookup_field='id'
感谢关注!!!