快速入门
使用drf框架对商品进行序列化后,传递给前台展示
使用drf中的序列化同django form表单类似,定义序列化文件 serializers.py :
from rest_framework import serializers from goods.models import Goods, GoodsCategory # class GoodsSerializer(serializers.Serializer): # name = serializers.CharField(max_length=50, required=True) # click_num = serializers.IntegerField(default=0) class CategorySerializer(serializers.ModelSerializer): class Meta: model = GoodsCategory fields = '__all__' # 序列化所有的字段 class GoodsSerializer(serializers.ModelSerializer): category = CategorySerializer() # 覆盖掉goods原来的category, 获取category所有信息 class Meta: model = Goods fields = '__all__' # 序列化所有的字段
在app的views中定义要序列化的 model:
from goods.models import Goods from goods.serializers import GoodsSerializer from rest_framework.views import APIView from rest_framework.response import Response from rest_framework import status class GoodsListView(APIView): """ List all snippets, or create a new snippet. """ def get(self, request, format=None): goods = Goods.objects.all() serializer = GoodsSerializer(goods, many=True) return Response(serializer.data) def post(self, request, format=None): serializer = GoodsSerializer(data=request.data) if serializer.is_valid(): serializer.save() return Response(serializer.data, status=status.HTTP_201_CREATED) return Response(serializer.errors, status=status.HTTP_400_BAD_REQUEST)
使用generics.GenericAPIView 和 mixins.ListModelMixin, mixins.CreateModelMixin 对代码进行封装
mixins 中的ListModelMixin CreateModelMixin类对上一步的代码用list create 方法进行了封装,所以需要重载 get post方法
from goods.models import Goods from goods.serializers import GoodsSerializer from rest_framework import generics, mixins class GoodsListView(mixins.ListModelMixin, mixins.CreateModelMixin, generics.GenericAPIView): """ List all snippets, or create a new snippet. """ queryset = Goods.objects.all() serializer_class = GoodsSerializer def get(self, request, *args, **kwargs): return self.list(request, *args, **kwargs) def post(self, request, *args, **kwargs): return self.create(request, *args, **kwargs)
ListCreateAPIView 继承了上面 使用的三个类,并对 get post方法进行了重载,使用它可以进一步简化 代码
下面是 ListCreateAPIView 源码
class ListCreateAPIView(mixins.ListModelMixin, mixins.CreateModelMixin, GenericAPIView): """ Concrete view for listing a queryset or creating a model instance. """ def get(self, request, *args, **kwargs): return self.list(request, *args, **kwargs) def post(self, request, *args, **kwargs): return self.create(request, *args, **kwargs)
使用ListCreateAPIView简化views.py 代码:
from goods.models import Goods from goods.serializers import GoodsSerializer from rest_framework import generics, mixins from rest_framework.pagination import PageNumberPagination class GoodsPagination(PageNumberPagination): page_size = 10 page_size_query_param = 'page_size' page_query_param = 'p' max_page_size = 100 class GoodsListView(generics.ListCreateAPIView): """ List all snippets, or create a new snippet. """ queryset = Goods.objects.all() serializer_class = GoodsSerializer pagination_class = GoodsPagination # 使用自定义的class对列表分页
ViewSet和router的使用
GenericViewSet 多继承GenericAPIView 和 ViewSetMixin
class GenericViewSet(ViewSetMixin, generics.GenericAPIView): pass
ViewSetMixin主要实现了两个方法, 实现 GET, POST 到 list create 等方法的动态绑定
class ViewSetMixin(object): """ view = MyViewSet.as_view({'get': 'list', 'post': 'create'}) """ @classonlymethod def as_view(cls, actions=None, **initkwargs): def initialize_request(self, request, *args, **kwargs)
使用实例views.py, 列出商品列表:
from goods.models import Goods from goods.serializers import GoodsSerializer from rest_framework import generics, mixins from rest_framework.pagination import PageNumberPagination from rest_framework import viewsets class GoodsPagination(PageNumberPagination): page_size = 10 page_size_query_param = 'page_size' page_query_param = 'p' max_page_size = 100 class GoodsListViewSet(mixins.ListModelMixin, viewsets.GenericViewSet): queryset = Goods.objects.all() serializer_class = GoodsSerializer pagination_class = GoodsPagination # 使用自定义的class对列表分页
显示的配置url,urls.py:
from goods.views import GoodsListViewSet goods_list = GoodsListViewSet.as_view({ 'get': 'list', }) urlpatterns = [ url(r'^goods/$', goods_list, name='goods_list-list'), ]
或者使用router配置url, 效果等同上一种:
from rest_framework.routers import DefaultRouter
router = DefaultRouter() router.register(r'goods', GoodsListViewSet) urlpatterns = [ url(r'^', include(router.urls)),]
mixins APIView viewsets之间的关系
mixins 中的类对应每一个每一个http请求操作方法
class CreateModelMixin(object): """ Create a model instance. # post在服务器新建一个资源 """ class ListModelMixin(object): """ List a queryset. # get 从服务器取出资源(一项或多项) """ class RetrieveModelMixin(object): """ Retrieve a model instance. # 取回一个实例 """ class UpdateModelMixin(object): """ Update a model instance. # put PATCH 在服务器更新资源 """ class DestroyModelMixin(object): """ Destroy a model instance. delete # 删除 """
GenericAPIView
在drf中最重要的就是 generics .GenericAPIView, GenericAPIView继承自APIView,而 APIView 是继承自django中的View.
GenericAPIView 使用属性实现了查询,分页 过滤等功能,具体用法观看文档
使用 mixins和APIView进行组合, 通过继承这些类进一步简化代码
viewsets
class GenericViewSet(ViewSetMixin, generics.GenericAPIView):
GenericAPIView 在前面已经介绍过了,这里面最重要的就是 ViewSetMixin, ViewSetMixin 主要实现了两个方法 as_view() 和 initialize_request 。
class ViewSetMixin(object): """ This is the magic. Overrides `.as_view()` so that it takes an `actions` keyword that performs the binding of HTTP methods to actions on the Resource. For example, to create a concrete view binding the 'GET' and 'POST' methods to the 'list' and 'create' actions... view = MyViewSet.as_view({'get': 'list', 'post': 'create'}) """ @classonlymethod def as_view(cls, actions=None, **initkwargs): def initialize_request(self, request, *args, **kwargs)
viewset使用方法在前面已经介绍过了,总结一下 mixins APIView viewsets 之间的关系
mixins:
- CreateModelMixin,
- ListModelMixin,
- RetrieveModelMixin,
- UpdateModelMixin,
- DestroyModelMixin
view:
GenericAPIView(APIView)
- RetrieveAPIView(mixins.RetrieveModelMixin, GenericAPIView)
- DestroyAPIView(mixins.DestroyModelMixin, GenericAPIView)
- UpdateAPIView(mixins.UpdateModelMixin, GenericAPIView)
- ListCreateAPIView(mixins.ListModelMixin,mixins.CreateModelMixin,GenericAPIView)
- RetrieveUpdateAPIView(mixins.RetrieveModelMixin, mixins.UpdateModelMixin,GenericAPIView)
- RetrieveDestroyAPIView(mixins.RetrieveModelMixin,mixins.DestroyModelMixin,GenericAPIView)
- RetrieveUpdateDestroyAPIView(mixins.RetrieveModelMixin,mixins.UpdateModelMixin, mixins.DestroyModelMixin,GenericAPIView):
viewsets
- ViewSet(ViewSetMixin, views.APIView)
- GenericViewSet(ViewSetMixin, generics.GenericAPIView)
- ReadOnlyModelViewSet(mixins.RetrieveModelMixin, mixins.ListModelMixin,GenericViewSet)
- ModelViewSet(mixins.CreateModelMixin, mixins.RetrieveModelMixin, mixins.UpdateModelMixin,mixins.DestroyModelMixin, mixins.ListModelMixin, GenericViewSet)
无论是viewset 还是 APIView 都离不开mixin,使用APIView和 mixin组合,更加灵活。使用viewset 代码更加简洁,但也更抽象。