DRF视图组件(2个视图基类、5个视图扩展类、9个视图子类、视图集和路由映射)
目录
- DRF视图组件(2个视图基类、5个视图扩展类、9个视图子类、视图集和路由映射)
- 2个视图基类
- mixins的5个视图扩展类
- generics的9个视图子类
- 视图集
- 自定制返回格式
- 自动生成路由(SimpleRouter)
- action装饰器
2个视图基类
原APIView
写法:
from rest_framework.views import APIViewclass publish(APIView):def get(self, request):publish_obj = models.Publish.objects.all()serializer = PublishSerializer(instance=publish_obj, many=True)return Response({'code': '200', 'msg': '查询成功', 'result': serializer.data})def post(self, request):serializer = PublishSerializer(data=request.data)if serializer.is_valid():serializer.save()return Response({'code': '200', 'msg': '添加成功', 'result': serializer.data})else:return Response({'code': '900', 'msg': serializer.errors})class publish_detail(APIView):def get(self, request, u_id):publish_obj = models.Publish.objects.get(id=u_id)serializer = PublishSerializer(instance=publish_obj)return Response({'code': '200', 'msg': '查询成功', 'result': serializer.data})def delete(self, request, u_id):passdef put(self, request, u_id):publish_obj = models.Author.objects.filter(pk=u_id).first()# 改对象必须传data和instanceserializer = PublishSerializer(instance=publish_obj, data=request.data)if serializer.is_valid():serializer.save()return Response({'code': '200', 'msg': "修改成功", 'result': serializer.data})else:return Response({'code': '201', 'msg': serializer.errors})
GenericAPIView类改写:
from rest_framework.generics import GenericAPIViewclass publish(GenericAPIView):queryset = models.Publish.objects.all()serializer_class = PublishSerializerdef get(self, request):publish_obj = self.get_queryset()serializer = self.get_serializer(instance=publish_obj, many=True)return Response({'code': '200', 'msg': '查询成功', 'result': serializer.data})def post(self, request):serializer = self.get_serializer(data=request.data)if serializer.is_valid():serializer.save()return Response({'code': '200', 'msg': '添加成功', 'result': serializer.data})else:return Response({'code': '900', 'msg': serializer.errors})class publish_detail(GenericAPIView):queryset = models.Publish.objects.all()serializer_class = PublishSerializerdef get(self, request, pk):publish_obj = self.get_object()serializer = self.get_serializer(instance=publish_obj)return Response({'code': '200', 'msg': '查询成功', 'result': serializer.data})def delete(self, request, pk):self.get_object().delete()return Response({'code': '200', 'msg': '删除成功'})def put(self, request, pk):publish_obj = self.get_object()# 改对象必须传data和instanceserializer = self.get_serializer(instance=publish_obj, data=request.data)if serializer.is_valid():serializer.save()return Response({'code': '200', 'msg': "修改成功", 'result': serializer.data})else:return Response({'code': '201', 'msg': serializer.errors})
queryset = models.Publish.objects.all()
:查询所有数据serializer_class = PublishSerializer
:获取序列化类(本文未展示)publish_obj = self.get_queryset()
:获取所有数据serializer = self.get_serializer(instance=publish_obj, many=True)
:使用定义好的序列化类self.get_object()
:这里不需要传入pk,直接用它定义好的方法,但是它默认识别的只有pk,取其他名会报错
mixins的5个视图扩展类
-
CreateModelMixin
:新增 -
ListModelMixin
:查询所有 -
DestroyModelMixin
:删除单条 -
UpdateModelMixin
:修改单条 -
RetrieveModelMixin
:查询单条
from rest_framework.generics import GenericAPIView
from rest_framework.mixins import CreateModelMixin, ListModelMixin, DestroyModelMixin, RetrieveModelMixin, \UpdateModelMixinclass publish(GenericAPIView, CreateModelMixin, ListModelMixin):queryset = models.Publish.objects.all()serializer_class = PublishSerializerdef get(self, request):res = super().list(request)return Response({'code': '200', 'msg': '查询成功', 'result': res.data})def post(self, request):res = super().create(request)print(type(res))return Response({'code': '200', 'msg': '添加成功', 'result': res.data})class publish_detail(GenericAPIView, RetrieveModelMixin, DestroyModelMixin, UpdateModelMixin):queryset = models.Publish.objects.all()serializer_class = PublishSerializerdef get(self, request, *args, **kwargs):res = super().retrieve(request, *args, **kwargs)return Response({'code': '200', 'msg': '查询成功', 'result': res.data})def delete(self, request, *args, **kwargs):res = super().destroy(request, *args, **kwargs)return Response({'code': '200', 'msg': '删除成功'})def put(self, request, *args, **kwargs):res = super().update(request, *args, **kwargs)return Response({'code': '200', 'msg': "修改成功", 'result': res.data})
res = super().list(request)
:调用ListModelMixin
类中的list方法可以省去查询数据和序列化的书写,下面的都一样- 注:res是一个 Response 实例,而不是一个序列化器实例,因此对返回值调用
.is_valid()
之类的方法会报AttributeError
generics的9个视图子类
CreateAPIView
:新增DestroyAPIView
:删除ListAPIView
:查询所有ListCreateAPIView
:查询所有和新增的合并RetrieveAPIView
:查询单个RetrieveDestroyAPIView
:查询单个和删除的合并RetrieveUpdateAPIView
:查询单个和修改的合并RetrieveUpdateDestroyAPIView
:查询单个、修改和删除的合并UpdateAPIView
:修改
from rest_framework.generics import ListCreateAPIView, RetrieveUpdateDestroyAPIViewclass publish(ListCreateAPIView):queryset = models.Publish.objects.all()serializer_class = PublishSerializerclass publish_detail(RetrieveUpdateDestroyAPIView):queryset = models.Publish.objects.all()serializer_class = PublishSerializer
视图集
# views.py
from rest_framework.viewsets import ModelViewSetclass publish(ModelViewSet):queryset = models.Publish.objects.all()serializer_class = PublishSerializer
# urls.py
from django.contrib import admin
from django.urls import path
from app import viewsurlpatterns = [path('publish/', views.publish.as_view({'get': 'list', 'post': 'create'})),path('publish/<str:pk>/', views.publish.as_view({'get': 'retrieve', 'put': 'update', 'delete': 'destroy'})),
]
- 此时就不需要再分一个publish_detail类了,ModelviewSet已经帮你把五个接口全部写好了,只需在路由层添加映射
'get': 'list'
:表示遇到get请求时执行list方法,其他的也是
自定制返回格式
-
不管是视图子类还是视图集,需要自定制返回字段时只需重写所需方法就行
-
例如我要自定制查询所有的返回值就重写list:
class publish(ListCreateAPIView):queryset = models.Publish.objects.all()serializer_class = PublishSerializerdef list(self, request, *args, **kwargs):res = super().list(request, *args, **kwargs)res.data = {"code": 200, "msg": "查询成功", "result": res.data}return Response(res.data)
res.data
默认返回的是一个包含多个字典的列表
自动生成路由(SimpleRouter)
# urls.py
from rest_framework.routers import SimpleRouter
from app import views# 实例对象
router = SimpleRouter()
# 将publish类注册,最左边的publish为浏览器输入的路由,最右边的publish是别名
router.register('publish', views.publish, 'publish')urlpatterns = [
]
# 将注册好的路由添加进urlpatterns
现在得到的路由其实就是http://127.0.0.1:8000/publish/
,调用的视图类是publish,并且pk它也会自动帮你写好
与SimpleRouter类似的还有DefaultRouter,他俩基本用法完全一致,唯一不同的是DefaultRouter会返回一个根路径
- SimpleRouter:
- DefaultRouter:
点进Api Root
后可以看到它返回了一个根路径
{"publish": "http://127.0.0.1:8000/publish/"
}
action装饰器
SimpleRouter自动生成路由后有一个弊端就是当绑定的类中没有get\path这种方法名时会注册失败
例如我现在有一个login方法,我想让他接受get请求实现查询单个的功能要,只需在上面价加个action装饰器
# views.py
from rest_framework.viewsets import ModelViewSet
from rest_framework.decorators import actionclass publish(ModelViewSet):@action(methods=['GET'], detail=False)def login(self, request)
action参数:(methods=None, detail=None, url_path=None, url_name=None, **kwargs):
methods
:包含被允许的请求方法detail
:指定是否需要提供对象的详细信息url_path
:指定自定义的 URL 路径url_name
:指定自定义的 URL 名称