**
假设一直存在models.py下有:
**
from django.db import models
class Goods(models.Model):
"""
商品
UEditorField:
"""
category = models.ForeignKey(GoodsCategory,verbose_name='商品类目')
goods_sn = models.CharField(max_length=50,default='',verbose_name='商品唯一货号')
name = models.CharField(max_length=300,verbose_name='商品名')
假设一直存在serilalizers.py下有:
from rest_framework import serializers
from goods.models import Goods
class CategorySerializer(serializers.ModelSerializer):
class Meta:
model = GoodsCategory
# 可以指定需要序列化的字段
# fields = ('name',)
# 或者直接"__all__"序列化所有字段
fields = '__all__'
APIView
from rest_framework.views import APIView
APIView(View)
作用:
----------View是django实现cbv方式需要继承的View,我相信drf为了实现cbv的方式所以也继承了View,这也就是drf最基本的APIView.没有什么特殊的地方,就是在drf中实现cbv方式编码。
举例:
from rest_framework.views import APIView
from .models import Goods
class GoodstListView(APIView):
"""
这里是对GoodstListView的解释信息,在浏览器可以看到这条信息
"""
# 获取数据
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):
# 和django不同的是data信息直接在request.data里面,因为drf在django
# 的request进行了一层封装,不是原生django的request
serializer = GoodsSerializer(data=request.data)
GenericAPIView
from rest_framework.generics import GenericAPIView
GenericAPIView(APIView)
------------很明显GenericAPIView继承了APIView,在APIView的基础上封装了一些方法,比如指定序列化对象的参数:serializer_class等。
GenericAPIView一般和mixins (from rest_framework import mixins)一起使用:
Class GoodsListView(mixins.ListModelMixin, GenericAPIView)
def get(self, request,*args, **kwargs):
return self.list(request, *args,**kwargs)
作用:
----------首先GoodsListView继承GenericAPIView,GenericAPIView继承APIView所以使用最最上面的方式肯定能实现的,但是需要自己写return Reaponse(serializer.data)这样的函数,
----------这个时候mixins.ListModelMixin的作用就体现出来了,他封装好了这种需要自己return的方式,只要重载def get(self, request,*args, **kwargs)函数就行了,就可以达到和手写和return Reaponse(serializer.data)这种方式实现序列化一样的效果。总结一句话就是,为了复用mixins.ListModelMixin (from rest_framework import mixins)经封装好了序列化的类,不用在手动return Response(serializer.data)了。
----------所以你需要达到什么样的功能,直接继承mixin下面的类就好了。比如我这里实现的是展示的功能就继承了mixins.ListModelMixin的类,如果你需要create方式来接受传过来的参数并save进数据库的话,就需要继承mixins.createModelMixin,并且重载他的def create(self, request,*args, **kwargs)函数就行了。需要什么功及继承什么类,排列组合就行。(mixin全部类如下:)
CreateModelMixin: post方式save进来数据库
ListModelMixin: get序列化展示数据
RetrieveModelMixin 获取数据详情
UpdateModelMixin 更新数据
DestroyModelMixin 删除数据
mixins+ GenericAPIView的排列组合
上面提到
Class GoodsListView(mixins.ListModelMixin, GenericAPIView)
def get(self, request,*args, **kwargs):
return self.list(request, *args,**kwargs)
----------当继承ListModelMixin的时候,这种方式一定要重载get方法。既然我们这种凡夫俗子都能想到能不能把需要的情况排列组合相互来,drf肯定已经实现了这样的功能。其实drf已经帮忙做了这种组合的继承,内置有很多像这里的Class GoodsListView(mixins.ListModelMixin, GenericAPIView)这种方式的继承,所以我们只要再继承GoodsListView就行了,不用再重载mixins.ListModelMixin下面的def get(self, request,*args,**keargs)方法.
类似于(mixins.ListModelMixin, GenericAPIView)这种排列组合的类路径在from rest_framework.generics下面,所有相关排列组合的继承如下所示(GenericAPIView也在下面):
class GenericAPIView(views.APIView):
pass # 这里是我省略的,因为源码太多,下面的类代码是源码
----------下面的这些类都是GenericAPIView和mixins中函数的排列组合来实现增删改查的功能所以我们继承这些已经帮我们排列组合好的类,就不用再重载那些get post函数了,因为这些类已经帮我们重载了!!
from rest_framework.generics:
class CreateAPIView(mixins.CreateModelMixin,
GenericAPIView):
"""
Concrete view for creating a model instance.
"""
def post(self, request, *args, **kwargs):
return self.create(request, *args, **kwargs)
class ListAPIView(mixins.ListModelMixin,
GenericAPIView):
"""
Concrete view for listing a queryset.
"""
def get(self, request, *args, **kwargs):
return self.list(request, *args, **kwargs)
class RetrieveAPIView(mixins.RetrieveModelMixin,
GenericAPIView):
"""
Concrete view for retrieving a model instance.
"""
def get(self, request, *args, **kwargs):
return self.retrieve(request, *args, **kwargs)
class DestroyAPIView(mixins.DestroyModelMixin,
GenericAPIView):
"""
Concrete view for deleting a model instance.
"""
def delete(self, request, *args, **kwargs):
return self.destroy(request, *args, **kwargs)
class UpdateAPIView(mixins.UpdateModelMixin,
GenericAPIView):
"""
Concrete view for updating a model instance.
"""
def put(self, request, *args, **kwargs):
return self.update(request, *args, **kwargs)
def patch(self, request, *args, **kwargs):
return self.partial_update(request, *args, **kwargs)
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)
class RetrieveUpdateAPIView(mixins.RetrieveModelMixin,
mixins.UpdateModelMixin,
GenericAPIView):
"""
Concrete view for retrieving, updating a model instance.
"""
def get(self, request, *args, **kwargs):
return self.retrieve(request, *args, **kwargs)
def put(self, request, *args, **kwargs):
return self.update(request, *args, **kwargs)
def patch(self, request, *args, **kwargs):
return self.partial_update(request, *args, **kwargs)
class RetrieveDestroyAPIView(mixins.RetrieveModelMixin,
mixins.DestroyModelMixin,
GenericAPIView):
"""
Concrete view for retrieving or deleting a model instance.
"""
def get(self, request, *args, **kwargs):
return self.retrieve(request, *args, **kwargs)
def delete(self, request, *args, **kwargs):
return self.destroy(request, *args, **kwargs)
class RetrieveUpdateDestroyAPIView(mixins.RetrieveModelMixin,
mixins.UpdateModelMixin,
mixins.DestroyModelMixin,
GenericAPIView):
"""
Concrete view for retrieving, updating or deleting a model instance.
"""
def get(self, request, *args, **kwargs):
return self.retrieve(request, *args, **kwargs)
def put(self, request, *args, **kwargs):
return self.update(request, *args, **kwargs)
def patch(self, request, *args, **kwargs):
return self.partial_update(request, *args, **kwargs)
def delete(self, request, *args, **kwargs):
return self.destroy(request, *args, **kwargs)
ViewSet & Router连用
from rest_framework import viewsets
class ViewSetMixin(object):
@classonlymethod
def as_view(cls, actions=None, **initkwargs):
# 手动省略其他
class ViewSet(ViewSetMixin, views.APIView):
"""
The base ViewSet class does not provide any actions by default.
"""
pass
---------- 可以发现ViewSet继承ViewSetMixin,views.APIView。ViewSetMixin重写了as_view()函数,表示调用的时候不再像以前一样在urls.py中ClassName.as_view(),换了按照他重写的方式来进行路由的匹配(这也是使用ViewSet系列的意义和作用)。
class GenericViewSet(ViewSetMixin, generics.GenericAPIView):
----------表明GenericViewSet具有ViewSetMixin和generics.GenericAPIView的功能。来自ViewSetMixin 的as_view()函数改变和来自generics.GenericAPIView可指定serializer_class表明需要序列化的序列化器
用viewsets的方式实现一个新的view:
class GoodsListView(mixins.ListModelMixin, viewsets.GenericViewSet)
queryset = Goods.objects.all()
serializer_class = GoodsSerializer
----------class GenericViewSet(ViewSetMixin,generics.GenericAPIView),其中ViewSetMixin只是改写了as_view()方法,generics.GenericAPIView只是继承于APIView,拥有了serializer_class指定序列化器的属性。由前面可知,没有继承generics.CreateAPIView这样的类,我们需要重载mixins.ListModelMixin 下的def list(self):函数才能实现数据展示和save进数据库,然而这里没有重载,怎么才能实现?有两种方式实现:
(1) 手动绑定get与mixins.ListModelMixin的list展示函数
app/urls.py下
from .views import GenericViewSet
goods-list = GenericViewSet.as_view({
‘get’:’list’})
urlpatterns = [
url(r’goods/$’, goods-list.name=’goods-list’)
]
(2) viewset+Router方式
apps/urls.py下:
from .views import GenericViewSet
from rest_framework.router import DefaultRouter
router = DefaultRouter()
router.register(r‘goods’, GenericViewSet )
urlpatterns = [
url(r’^’,include(router.urls))
]