视图组件

写一个出版社的增删查改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