DRF 视图
DRF 视图
基于类的视图的一个主要优点是它们允许您组合可重用行为的方式。REST框架通过提供许多提供常用模式的预构建视图来利用这一点。
REST框架提供的通用视图允许您快速构建与您的数据库模型紧密相关的API视图。
如果通用视图不适合您的API需求,您可以直接使用常规
APIView
类,或者重用通用视图使用的mixins和基类来组成您自己的可重用通用视图集。
初始态
class PublisherListView(APIView):
def get(self, request):
queryset = models.Publisher.objects.all()
ser_obj = PublisherModelSerializer(queryset, many=True)
return Response(ser_obj.data)
def post(self, request):
ser_obj = PublisherModelSerializer(data=self.request.data)
if ser_obj.is_valid():
ser_obj.save()
return Response('ok')
else:
return Response(ser_obj.errors)
class AuthorListView(APIView):
def get(self, request):
queryset = models.Author.objects.all()
ser_obj = AuthorModelSerializer(queryset, many=True)
return Response(ser_obj.data)
def post(self, request):
ser_obj = AuthorModelSerializer(data=self.request.data)
if ser_obj.is_valid():
ser_obj.save()
return Response('ok')
else:
return Response(ser_obj.errors)
进化
python mixin(混合类):不能单独使用,和其它类搭配起来使用(利用了Python支持多继承)
class GenericView(APIView):
queryset = None
serializer = None
def get_queryset(self):
return self.queryset.all()
class ListMixin(object):
# python mixin(混合类):不能单独使用,和其它类搭配起来使用(利用了Python支持多继承)
def get(self, request):
queryset = self.get_queryset()
ser_obj = self.serializer(queryset, many=True)
return Response(ser_obj.data)
class CreateMixin(object):
def post(self, request):
ser_obj = self.serializer(data=self.request.data)
if ser_obj.is_valid():
ser_obj.save()
return Response('ok')
else:
return Response(ser_obj.errors)
class AuthorListView(GenericView, ListMixin, CreateMixin):
queryset = models.Author.objects.all()
serializer = AuthorModelSerializer
class PublisherListView(GenericView, ListMixin, CreateMixin):
queryset = models.Publisher.objects.all()
serializer = PublisherModelSerializer
超进化
提取混合类,将混合类继续组合!
把增删改查查五动作拆分出来,写成独立的混合。
class GenericView(APIView):
queryset = None
serializer_class = None
def get_queryset(self):
return self.queryset.all()
class ListMixin(object):
# python mixin(混合类):不能单独使用,和其它类搭配起来使用(利用了Python支持多继承)
def get(self, request):
queryset = self.get_queryset()
ser_obj = self.serializer_class(queryset, many=True)
return Response(ser_obj.data)
class CreateMixin(object):
# python Mixin 混合类,不可单独使用
def post(self, request):
ser_obj = self.serializer_class(data=self.request.data)
if ser_obj.is_valid():
ser_obj.save()
return Response('ok')
else:
return Response(ser_obj.errors)
class RetrieveMixin(object):
def get(self, request, pk):
obj = self.get_queryset().filter(pk=pk).first()
if obj:
pass
ser_boj = self.serializer_class(obj)
return Response(ser_boj.data)
else:
return Response('无效id')
class UpdateMixin(object):
def put(self, request, pk):
obj = self.get_queryset().filter(pk=pk).first()
if obj:
ser_boj = self.serializer_class(instance=obj, data=self.request.data, partial=True)
if ser_boj.is_valid():
ser_boj.save()
return Response(ser_boj.data)
else:
return Response(ser_boj.errors)
else:
return Response('无效id')
class DestroyMixin(object):
def delete(self, request, pk):
obj = self.get_queryset().filter(pk=pk).first()
if obj:
obj.delete()
return Response('删除成功')
else:
return Response('无效id')
class AuthorListView(GenericView, ListMixin, CreateMixin):
queryset = models.Author.objects.all()
serializer_class = AuthorModelSerializer
class AuthorDetailView(GenericView, RetrieveMixin, UpdateMixin, DestroyMixin):
queryset = models.Author.objects.all()
serializer_class = AuthorModelSerializer
class PublisherListView(GenericView, ListMixin, CreateMixin):
queryset = models.Publisher.objects.all()
serializer_class = PublisherModelSerializer
class PublisherDetailView(GenericView, RetrieveMixin, UpdateMixin, DestroyMixin):
queryset = models.Publisher.objects.all()
serializer_class = PublisherModelSerializer
其实内置已经提供了
from rest_framework.generics import ListAPIView, CreateAPIView, RetrieveAPIView, UpdateAPIView, DestroyAPIView
究极进化
一张表要写两个视图,定义两次 queryset和serializer_class 重复!
from rest_framework.viewsets import GenericViewSet
GenericViewSet重写了as_view()
方法,实现了根据请求的方法执行具体的类方法
路由注册的时候,利用actions参数,实现路由的定向分发 而不是简单的 反射
路由都重复写两条!
还可以利用内置的DefaultRouter来实现路由的注册
from rest_framework.routers import DefaultRouter
router = DefaultRouter()
router.register('pulisher', views.PublisherViewSet)
urlpatterns += router.urls
视图
from rest_framework.viewsets import ModelViewSet
class PublisherViewSet(ModelViewSet):
queryset = models.Publisher.objects.all()
serializer_class = PublisherModelSerializer
路由
url(r'^publishers/$', views.PublisherViewSet.as_view(actions={'get': 'list', 'post': 'create'})), # 出版社列表
url(r'^publishers/(?P<pk>\d+)/$', views.PublisherViewSet.as_view(
actions={'get': 'retrieve', 'post': 'update', 'delete': 'destroy'})), # 出版社详情
总结
一般使用
一张表,两个视图
from rest_framework.generics import ListCreateAPIView, RetrieveUpdateDestroyAPIView
class PublisherListView(ListCreateAPIView):
queryset = models.Publisher.objects.all()
serializer_class = PublisherModelSerializer
class PublisherDetailView(RetrieveUpdateDestroyAPIView):
queryset = models.Publisher.objects.all()
serializer_class = PublisherModelSerializer
一张表,一个视图
from rest_framework.viewsets import ModelViewSet
class PublisherViewSet(ModelViewSet):
queryset = models.Publisher.objects.all()
serializer_class = PublisherModelSerializer
路由:
url(r'^publishers/$', views.PublisherViewSet.as_view(actions={'get': 'list', 'post': 'create'})),
url(r'^publishers/(?P<pk>\d+)/$', views.PublisherViewSet.as_view(
actions={'get': 'retrieve', 'post': 'update', 'delete': 'destroy'})),
view ,django CBV的view,拥有 dispatch()
方法,通过反射向CBV中分发请求
APIView,继承view ,重写了 dispatch()
方法,增加了 内容协商,版本控制,认证,权限,限制功能,并将原来 django 的 HttpRequest对象 更新为 rest_framework 重写的 Request 对象,在重写的 Request 对象中,原来的 request 对象变为 request._request ,还新增了 request.data ,为根据 request.content_type 解析出的数据, request.query_params 为URL中的参数
GenericAPIView,继承于APIView ,增加了 get_queryset()
get_serializer()
paginator()
方法,对应的功能是 queryset ,序列化,分页,只需赋予 queryset对象,序列化类,分页类即可自动完成操作。
ViewSetMixin ,重写 as_view()
方法,根据路由url中 action参数直接将 一个请求绑定一个方法,然后再用 GenericAPIView 中的 dispatch()
方法进行分发
GerericViewSet ,继承于 ViewSetMixin ,GenericAPIView
ListModelMixin,实现 list()
方法,返回一个queryset的列表,对应于 get
CreateModelMixin, 实现create()
方法 ,创建一个实例,对应于 post
RetrieveModelMixin,实现retrieve()
方法, 返回一个具体实例,对应于 get
UpdateModelMixin,实现update()
方法 ,对某个实例进行更新,对应于 put/patch
DestroyModelMixin,实现destroy()
方法,删除某个实例,对应于 delete
ModelViewSet , 继承于 GerericViewSet ,ListModelMixin,CreateModelMixin,RetrieveModelMixin,UpdateModelMixin,DestroyModelMixin