零、视图家族 Django REST framework 为了方便视图类的操作,构建了包括以下几种视图类和工具集:
views:API视图
generics:工具视图
mixins:视图工具集
viewsets:视图集
一、GenericAPIView:视图家族的基类 generics.py 中的 GenericAPIView 作为视图家族中重要的基类,在后面的接口代码的实现中起到重要作用。
用 Pycharm 可以看到 GenericAPIView 的方法和继承关系:
GenericAPIView 继承自 APIView,使用兼容 APIView,也就是说依旧可以使用 get,post等方法。
但是,这里 GenericAPIView 封装了更多有趣的方法。
get_queryset(): 从类属性 queryset 中获得 model 的 queryset 数据
get_object(): 通过有名分组 pk 确定唯一操作对象 自定义主键的有名分组 :lookup_field = ‘id’
get_serializer():从类属性 serializer_class 中获得serializer 的序列化类
二、Mixins:视图工具集 mixins.py
:视图工具集,用来辅助 GenericAPIView
包含有五个工具类文件,六个工具类方法:
CreateModeMixin:
ListModelMixin:
RetrieveModelMixin:
UpdateModelMixin:
单整体改: update
单局部改: partial_update
DestroyModelMixin:
单删: destroy,一般不使用该方法,或重写方法利用字段is_delete 来实现删除操作。
1.群查 查看源码
class ListModelMixin : """ List a queryset. """ def list (self, request, *args, **kwargs ): queryset = self.filter_queryset(self.get_queryset()) page = self.paginate_queryset(queryset) if page is not None : serializer = self.get_serializer(page, many=True ) return self.get_paginated_response(serializer.data) serializer = self.get_serializer(queryset, many=True ) class ListModelMixin : """ List a queryset. """ def list (self, request, *args, **kwargs ): queryset = self.filter_queryset(self.get_queryset()) page = self.paginate_queryset(queryset) if page is not None : serializer = self.get_serializer(page, many=True ) return self.get_paginated_response(serializer.data) serializer = self.get_serializer(queryset, many=True ) return Response(serializer.data)
代码实现 继承工具类可以简化请求函数的实现体,但是必须继承 GenericAPIView,因为需要 GenericAPIView 提供类属性和方法。
工具类方法返回值是 Response 对象,可以用 response.data 拿到,扔给之前封装的APIResponse 类实现格式。
views.py
class BookListGenericAPIView (ListModelMixin, GenericAPIView): queryset = models.Book.objects.filter (is_delete=False ) serializer_class = serializers.BookModelSerializer def get (self, request, *args, **kwargs ): response = self.list (request, *args, **kwargs) class BookListGenericAPIView (ListModelMixin, GenericAPIView): queryset = models.Book.objects.filter (is_delete=False ) serializer_class = serializers.BookModelSerializer def get (self, request, *args, **kwargs ): response = self.list (request, *args, **kwargs) return APIResponse(results=response.data)
urls.py
from django.conf.urls import urlfrom api import views urlpatterns = [ url(r'^v3/books/$' , views.BookListGenericAPIView.as_view()), url(from django.conf.urls import urlfrom api import views urlpatterns = [ url(r'^v3/books/$' , views.BookListGenericAPIView.as_view()), url(r'^v3/books/(?P.*)/$' , views.BookListGenericAPIView.as_view()), ]
测试接口
2.单查 查看源码
class RetrieveModelMixin : """ Retrieve a model instance. """ def retrieve (self, request, *args, **kwargs ): instance = self.get_object() serializer = self.get_serializer(instance) class RetrieveModelMixin : """ Retrieve a model instance. """ def retrieve (self, request, *args, **kwargs ): instance = self.get_object() serializer = self.get_serializer(instance) return Response(serializer.data)
代码实现 class BookListGenericAPIView (ListModelMixin, RetrieveModelMixin, GenericAPIView): queryset = models.Book.objects.filter (is_delete=False ) serializer_class = serializers.BookModelSerializer def get (self, request, *args, **kwargs ): if 'pk' in kwargs: response = self.retrieve(request, *args, **kwargs) else : response = self.list (request, *args, **kwargs) class BookListGenericAPIView (ListModelMixin, RetrieveModelMixin, GenericAPIView): queryset = models.Book.objects.filter (is_delete=False ) serializer_class = serializers.BookModelSerializer def get (self, request, *args, **kwargs ): if 'pk' in kwargs: response = self.retrieve(request, *args, **kwargs) else : response = self.list (request, *args, **kwargs) return APIResponse(results=response.data)
测试接口
3.单增 查看源码
查看 CreateModelMixin
源码
class CreateModelMixin : """ Create a model instance. """ def create (self, request, *args, **kwargs ): serializer = self.get_serializer(data=request.data) serializer.is_valid(raise_exception=True ) self.perform_create(serializer) headers = self.get_success_headers(serializer.data) return Response(serializer.data, status=status.HTTP_201_CREATED, headers=headers) def perform_create (self, serializer ): serializer.save() def get_success_headers (self, data ): try : return {'Location' : str (data[api_settings.URL_FIELD_NAME])} except (TypeError, KeyError): class CreateModelMixin : """ Create a model instance. """ def create (self, request, *args, **kwargs ): serializer = self.get_serializer(data=request.data) serializer.is_valid(raise_exception=True ) self.perform_create(serializer) headers = self.get_success_headers(serializer.data) return Response(serializer.data, status=status.HTTP_201_CREATED, headers=headers) def perform_create (self, serializer ): serializer.save() def get_success_headers (self, data ): try : return {'Location' : str (data[api_settings.URL_FIELD_NAME])} except (TypeError, KeyError): return {}
代码实现 可以看到这个类就是把之前单增的方法封装在一起方便调用
class BookListGenericAPIView (ListModelMixin, CreateModelMixin, GenericAPIView): queryset = models.Book.objects.filter (is_delete=False ) serializer_class = serializers.BookModelSerializer def post (self, request, *args, **kwargs ): response = self.create(request, *args, **kwargs) class BookListGenericAPIView (ListModelMixin, CreateModelMixin, GenericAPIView): queryset = models.Book.objects.filter (is_delete=False ) serializer_class = serializers.BookModelSerializer def post (self, request, *args, **kwargs ): response = self.create(request, *args, **kwargs) return APIResponse(results=response.data)
测试接口
4.单改 查看源码 class UpdateModelMixin : """ Update a model instance. """ def update (self, request, *args, **kwargs ): partial = kwargs.pop('partial' , False ) instance = self.get_object() serializer = self.get_serializer(instance, data=request.data, partial=partial) serializer.is_valid(raise_exception=True ) self.perform_update(serializer) if getattr (instance, '_prefetched_objects_cache' , None ): instance._prefetched_objects_cache = {} return Response(serializer.data) def perform_update (self, serializer ): serializer.save() def partial_update (self, request, *args, **kwargs ): kwargs['partial' ] = True class UpdateModelMixin : """ Update a model instance. """ def update (self, request, *args, **kwargs ): partial = kwargs.pop('partial' , False ) instance = self.get_object() serializer = self.get_serializer(instance, data=request.data, partial=partial) serializer.is_valid(raise_exception=True ) self.perform_update(serializer) if getattr (instance, '_prefetched_objects_cache' , None ): instance._prefetched_objects_cache = {} return Response(serializer.data) def perform_update (self, serializer ): serializer.save() def partial_update (self, request, *args, **kwargs ): kwargs['partial' ] = True return self.update(request, *args, **kwargs)
代码实现 class BookListGenericAPIView (ListModelMixin, UpdateModelMixin, GenericAPIView): queryset = models.Book.objects.filter (is_delete=False ) serializer_class = serializers.BookModelSerializer def put (self, request, *args, **kwargs ): response = self.update(request, *args, **kwargs) return APIResponse(results=response.data) def patch (self, request, *args, **kwargs ): response = self.partial_update(request, *args, **kwargs) class BookListGenericAPIView (ListModelMixin, UpdateModelMixin, GenericAPIView): queryset = models.Book.objects.filter (is_delete=False ) serializer_class = serializers.BookModelSerializer def put (self, request, *args, **kwargs ): response = self.update(request, *args, **kwargs) return APIResponse(results=response.data) def patch (self, request, *args, **kwargs ): response = self.partial_update(request, *args, **kwargs) return APIResponse(results=response.data)
测试接口
修改成功