zoukankan      html  css  js  c++  java
  • 视图组件

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

  • 相关阅读:
    齐文词根词缀---1、第一讲
    元音发音规则
    英语重读规则
    英语单词重读规则
    unicode,ansi,utf-8,unicode big endian编码的区别
    Netty中粘包和拆包的解决方案
    【转载】 DirectByteBuffer内存释放
    Netty 中ChannelOption的含义以及使用的场景Netty 中ChannelOption的含义以及使用的场景
    Connection reset原因分析和解决方案
    Netty实现Socket
  • 原文地址:https://www.cnblogs.com/zhangguosheng1121/p/11133277.html
Copyright © 2011-2022 走看看