写一个出版社的增删查改resful接口
models.py
class Book(models.Model):
name = models.CharField(max_length=32)
price = models.DecimalField(max_digits=5, decimal_places=2)
publish_date = models.DateField()
category = models.IntegerField(choices=((0, '文学类'), (1, '情感类')), default=1, null=True)
publish = models.ForeignKey(to='Publish', on_delete=models.CASCADE, null=True)
authors = models.ManyToManyField(to='Author')
def __str__(self):
return self.name
class Author(models.Model):
name = models.CharField(max_length=32)
age = models.IntegerField()
class Publish(models.Model):
name = models.CharField(max_length=32)
city = models.CharField(max_length=32)
email = models.EmailField()
myser.py
from rest_framework import serializers
from app01 import models
class PublishSerializers(serializers.ModelSerializer):
class Meta:
model = models.Publish
fields = '__all__'
urls.py
url(r'^publish/$', views.Publish.as_view()), url(r'^publish/(?P<pk>\d+)$', views.PublishDetail.as_view()),
一、基本使用
views.py
from rest_framework.views import APIView
from app01.myser import PublishSerializers
from app01 import models
from rest_framework.response import Response
class Publish(APIView):
def get(self, request):
publish_list = models.Publish.objects.all()
bs = PublishSerializers(publish_list, many=True)
# 序列化数据
return Response(bs.data)
def post(self, request):
# 添加一条数据
print(request.data)
bs = PublishSerializers(data=request.data)
if bs.is_valid():
bs.save() # 生成记录
return Response(bs.data)
else:
return Response(bs.errors)
class PublishDetail(APIView):
def get(self, request, pk):
publish_obj = models.Publish.objects.filter(pk=pk).first()
bs = PublishSerializers(publish_obj, many=False)
return Response(bs.data)
def put(self, request, pk):
publish_obj = models.Publish.objects.filter(pk=pk).first()
bs = PublishSerializers(data=request.data, instance=publish_obj)
if bs.is_valid():
bs.save() # update
return Response(bs.data)
else:
return Response(bs.errors)
def delete(self, request, pk):
models.Publish.objects.filter(pk=pk).delete()
return Response()
二、基于mixins,generics 封装的视图
views.py
# 新增 查找 查取一条 修改 删除
from rest_framework.mixins import CreateModelMixin, ListModelMixin, RetrieveModelMixin, UpdateModelMixin, DestroyModelMixin
# GenricAPIView:继承自APIView,提供as_view()等,获取当前视图类中queryset和serializer_class ,
# 用于给ListModelMixin和CreateModelMixin使用。
from rest_framework.generics import GenericAPIView
class Publish(CreateModelMixin, ListModelMixin, GenericAPIView):
# 指定要序列化的数据
queryset = models.Publish.objects.all() # 这里的all可以不写,会走源码里面的all, 但一般情况下都会写
# 序列化的对象
serializer_class = PublishSerializers
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 PublishDetail(RetrieveModelMixin, UpdateModelMixin, DestroyModelMixin, GenericAPIView):
queryset = models.Publish.objects.all()
serializer_class = PublishSerializers
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 delete(self, request, *args, **kwargs):
return self.destroy(request, *args, **kwargs)
三、使用generics 类下 ListCreateAPIView,RetrieveUpdateDestroyAPIView
views.py
# 查所有、新增 查一条、修改、删除
from rest_framework.generics import ListCreateAPIView, RetrieveUpdateDestroyAPIView
class Publish(ListCreateAPIView):
queryset = models.Publish.objects.all()
serializer_class = PublishSerializers
class PublishDetail(RetrieveUpdateDestroyAPIView):
queryset = models.Publish.objects.all()
serializer_class = PublishSerializers
源码分析:
①ListCreateAPIView是继承了CreateModelMixin, ListModelMixin以及GenericAPIView,在里面封装了get所有与post方法

②RetrieveUpdateDestroyAPIView继承了RetrieveModelMixin, UpdateModelMixin, DestroyModelMixin以及
GenericAPIView,在里面封装了get单条、put/patch方法和delete方法

四、使用viewsets :五个接口写在一个类中
urls.py
url(r'^publish/$', views.Publish.as_view({'get':'list','post':'create'})),
url(r'^publish/(?P<pk>\d+)/$', views.Publish.as_view({'get':'retrieve','put':'update','delete':'destroy'})),
views.py
from rest_framework.viewsets import ModelViewSet
class PublishView(ModelViewSet):
queryset=models.Publish.objects.all()
serializer_class=PublishSerializers
源码分析:
ModelViewSet继承了增查改删的所有方法

然后点进GenericViewSet里面去看一下这个类的源码

继承了ViewSetMixin与generics.GenericAPIView,然后我们点进去看一下ViewSetMixin

这里面翻译出来:
''这就是魔法。重写`.as_View()`以便它使用执行,将HTTP方法绑定到资源上的操作。例如,要创建绑定“get”和“post”方法的具体视图到“list”和“create”操作…,view=myviewset.as_view('get':'list'、'post':'create')''
然后往下翻发现重写了as_view方法
这里的as_views方法比原来的方法中多了一个actions参数,那么这个actions参数是用来接收哪个值呢?分析一下,我们去写的路由里看一下
这个actions就是路由配置的字典{'get': 'list', 'post': 'create'},一旦继承了ViewSetMixin,在路由配置的时候必须把这个字典传过去,如果不传会抛异常

然后继续往下看发现一个view方法,原来有一个view,而这个view是重写的,是最核心的代码,来看一下

这个method与action分别指的是字典里的key与value

把method与action取出来,通过getattr去找list,再通过setattr把值赋给了get,所以当我们执行get请求,源码里面执行的是list方法
所以当我们发不同的请求时,能够执行映射关系相对应的方法。
分析:ViewSetMixin重写了as_view方法

from rest_framework.viewsets import ViewSetMixin
from rest_framework.views import APIView # 因为ViewSetMixin里面没有继承APIView,所有要导入
class Publish(ViewSetMixin, APIView): # ViewSetMixin这个类必须要写在APIView的前面
def a(self, request):
return Response()
url(r'^a/$', views.Publish.as_view({'get': 'a'}))
请求get会执行a方法
来源:https://www.cnblogs.com/zhangguosheng1121/p/11133277.html


