CBV与FBV

CBV之前说过就是在view.py里写视图类,在序列化时用过,FBV就是常用的视图函数,两者的功能都可以实现功能,但是在restful规范方面的话,CBV更方便,FBV还要用request.method来判断是get,put,post等的,在CBV里要用什么就定义什么方法,根据请求的方法自动进入对应的CBV的方法里,节省了判断请求类型的过程

View与APIView

APIView就是在View上做了二次封装,多了一些功能而已,View是django自带的视图组件

在 前后端分离djangorestframework——序列化与反序列化数据 这篇文章中(所以接下来用到的数据还是这篇文章里用到的数据),利用了DRF的序列化与反序列化,感受了下DRF的特性,但其实视图部分的代码还是有点冗余,假如以后有上百个url,就要给上百个url写对应的视图类,然后对数据的增删改查,都要重写一次,这样功能是可以实现,但是太low了,需要改善下

View的第一次改版

每次在重复书写的是数据库表的操作,序列化类的操作,以及不同的请求方式对应的视图类的方法,所以可以微调一下:

修改数据库表和序列化类,重新定义一个类,代替操作,此后这个GenericView类可以被所有的视图类继承了,简直是一劳永逸的

再重组请求方式对应的方法:

访问页面看有没有问题:

添加一个字段看看:

成功:

可能你访问list时还没看到数据,打开数据库库查看是有的,多刷新几次页面就有了:

好的,把剩下的对单调数据操作的也改了

全部代码:

# coding:utf-8
from django.shortcuts import HttpResponse
from django.views import View
from demo1 import models
from django.core import serializers
from rest_framework.views import APIView
from rest_framework.response import Response
from demo1.serializers import BookSerializer

class OldBookView(View):
    # def get(self, request):
    #     book_list = models.Book.objects.values("id", "title", 'pub_time','publisher')
    #     book_list = list(book_list)
    #     ret = []
    #     for field in book_list:
    #         pub_id = field['publisher']
    #         publish_obj = models.Publisher.objects.filter(id=pub_id).first()
    #         field['publisher'] = {
    #             'id':pub_id,
    #             'title':publish_obj.title
    #         }
    #         ret.append(field)
    #
    #     return JsonResponse(ret, safe=False, json_dumps_params={'ensure_ascii': False})

    def get(self, request):
        book_list = models.Book.objects.all()
        ret = serializers.serialize('json', book_list, ensure_ascii=False)
        return HttpResponse(ret)

class GenericAPIView(APIView):
    query_set = None
    serializer_class = None

    def get_queryset(self):
        return self.query_set

    def get_serializer(self, *args, **kwargs):
        return self.serializer_class(*args, **kwargs)

# Mixin字段的都是混合类,需要混合继承
class ListModelMixin(object):
    def list(self, request):
        book_list = self.get_queryset()
        ret = self.get_serializer(book_list, many=True)
        return Response(ret.data)

class CreateModelMixin(object):
    def create(self, request):
        serialize = self.get_serializer(data=request.data)
        if serialize.is_valid():
            # save是存储
            serialize.save()
            return Response(serialize.data)
        else:
            return Response(serialize.errors)

class BookView(GenericAPIView, CreateModelMixin, ListModelMixin):
    query_set = models.Book.objects.all()
    serializer_class = BookSerializer

    def get(self, request):
        # book_list = self.get_queryset()
        # ret = self.get_serializer(book_list, many=True)
        # return Response(ret.data)
        return self.list(request)

    def post(self, request):
        # serialize = self.get_serializer(data=request.data)
        # if serialize.is_valid():
        #     serialize.save()
        #     return Response(serialize.data)
        # else:
        #     return Response(serialize.errors)
        return self.create(request)

class RetrieveModelMixin(object):
    def list(self, request, id):
        book_obj = self.get_queryset().filter(id=id).first()
        ret = self.get_serializer(book_obj)
        return Response(ret.data)

class RetrieveUpdateModelMixin(object):
    def update(self, request, id):
        book_obj = self.get_queryset().filter(id=id).first()
        # partial参数表示只对部分数据验证
        serialize = self.get_serializer(book_obj, data=request.data, partial=True)
        if serialize.is_valid():
            serialize.save()
            return Response(serialize.data)
        else:
            return Response(serialize.errors)

class RetrieveDestoryModelMixin(object):
    def destory(self, request, id):
        book_obj = self.get_queryset().filter(id=id).exists()
        if not book_obj:
            return Response('不存在id为%s的数据,请重试' % id)
        else:
            self.get_queryset().filter(id=id).delete()
            return Response("删除成功")

class BookEditView(GenericAPIView, RetrieveModelMixin, RetrieveUpdateModelMixin, RetrieveDestoryModelMixin):
    query_set = models.Book.objects.all()
    serializer_class = BookSerializer

    def get(self, request, id):
        # book_obj = models.Book.objects.filter(id=id).first()
        # ret = BookSerializer(book_obj)
        # return Response(ret.data)
        return self.list(request, id)

    def put(self, request, id):
        # book_obj = models.Book.objects.filter(id=id).first()
        # # partial参数表示只对部分数据验证
        # serialize = BookSerializer(book_obj, data=request.data, partial=True)
        #
        # if serialize.is_valid():
        #     # print(serialize.validated_data)
        #     # save是存储
        #     serialize.save()
        #     return Response(serialize.data)
        # else:
        #     return Response(serialize.errors)
        return self.update(request, id)

    def delete(self, request, id):
        # book_obj = models.Book.objects.filter(id=id).exists()
        # if not book_obj:
        #     return Response('不存在id为%s的数据,请重试' % id)
        # else:
        #     models.Book.objects.filter(id=id).delete()
        #     return Response("删除成功")
        return self.destory(request, id)

修改视图CBV-第一版

访问:

修改:

删除:

没有问题

View的第二次改版

有几个视图类继承好多个类,再次微调,再定义两个类只是继承那些类,然后视图类再继承此类,相对刚才没有做任何改动,就多了一个中间父类而已

View的第三次改版

还有个问题,看url,都是对Book表的操作,但是却有两个视图类来处理,不太符合restful规范

修改url,给as_view添加一个字典参数,但是默认as_view是不可以传参的,所以我们需要自己封装一个可以传参的类 

补充,我传的as_view参数中,对单条数据修改的retrieve的get方式由之前的"get":"list"已经改成了'get':'retrieve',对应的自定义RetrieveMixin里的方法也由list改成了retrieve,因为和上面对多条数据的"get":"list" 重复了,为了防止报错,所以修改了

定义类,修改as_view传参:

具体的逻辑代码就不写了,因为DRF自带了

直接用DRF定义的View——ModelViewSet

view.py文件,ModelViewSet用的不是query_set而是queryset,需要改下:

url要做稍微的调整,ModelViewSet用的是pk,还得把id改为pk:

好的其他不用作任何更改

访问:

添加:

修改:

删除:

数据库里已经没有id为7的

是的,就是这么方便

全部代码:

url:

from django.urls import path, re_path, include
# from demo1.views import BookView, BookEditView, BookModelViewSet
from demo1.views import BookModelViewSet

urlpatterns = [
    path('list', BookModelViewSet.as_view({'get': 'list', 'post': 'create'})),
    path('retrieve/<int:pk>', BookModelViewSet.as_view({'get': 'retrieve',
                                                        'put': 'update',
                                                        'delete': 'destroy'})),

]

view:

# coding:utf-8
from demo1 import models
from demo1.serializers import BookSerializer

from rest_framework.viewsets import ModelViewSet

class BookModelViewSet(ModelViewSet):
    queryset = models.Book.objects.all()
    serializer_class = BookSerializer

当然,如果你还是想用自己定义那些方法类,可以这样:

全部代码:相关的类名做了稍微的调整

# coding:utf-8
from django.shortcuts import HttpResponse
from django.views import View
from demo1 import models
from django.core import serializers
from rest_framework.views import APIView
from rest_framework.response import Response
from demo1.serializers import BookSerializer

from rest_framework.viewsets import ViewSetMixin

class GenericAPIView(APIView):
    query_set = None
    serializer_class = None

    def get_queryset(self):
        return self.query_set

    def get_serializer(self, *args, **kwargs):
        return self.serializer_class(*args, **kwargs)

# Mixin字段的都是混合类,需要混合继承
class ListModelMixin(object):
    def list(self, request):
        book_list = self.get_queryset()
        ret = self.get_serializer(book_list, many=True)
        return Response(ret.data)

class CreateModelMixin(object):
    def create(self, request):
        serialize = self.get_serializer(data=request.data)
        if serialize.is_valid():
            # save是存储
            serialize.save()
            return Response(serialize.data)
        else:
            return Response(serialize.errors)

class RetrieveModelMixin(object):
    def retrieve(self, request, id):
        book_obj = self.get_queryset().filter(id=id).first()
        ret = self.get_serializer(book_obj)
        return Response(ret.data)

class RetrieveUpdateModelMixin(object):
    def update(self, request, id):
        book_obj = self.get_queryset().filter(id=id).first()
        # partial参数表示只对部分数据验证
        serialize = self.get_serializer(book_obj, data=request.data, partial=True)
        if serialize.is_valid():
            serialize.save()
            return Response(serialize.data)
        else:
            return Response(serialize.errors)

class RetrieveDestoryModelMixin(object):
    def destroy(self, request, id):
        book_obj = self.get_queryset().filter(id=id).exists()
        if not book_obj:
            return Response('不存在id为%s的数据,请重试' % id)
        else:
            self.get_queryset().filter(id=id).delete()
            return Response("删除成功")

class RetrieveUpdateDestroyAPIView(GenericAPIView, RetrieveModelMixin, RetrieveUpdateModelMixin,
                                   RetrieveDestoryModelMixin):
    pass

class ListCreateAPIView(GenericAPIView, ListModelMixin, CreateModelMixin):
    pass

class BookView(ListCreateAPIView):
    query_set = models.Book.objects.all()
    serializer_class = BookSerializer

    def get(self, request):

        return self.list(request)

    def post(self, request):

        return self.create(request)

class BookEditView(RetrieveUpdateDestroyAPIView):
    query_set = models.Book.objects.all()
    serializer_class = BookSerializer

    def get(self, request, id):
        return self.retrieve(request, id)

    def put(self, request, id):

        return self.update(request, id)

    def delete(self, request, id):

        return self.destroy(request, id)

class ModelViewSet(ViewSetMixin, ListModelMixin, CreateModelMixin, RetrieveUpdateModelMixin, RetrieveModelMixin,
                 RetrieveDestoryModelMixin):
    pass

class BookModelViewSet(ModelViewSet):
    queryset = models.Book.objects.all()
    serializer_class = BookSerializer

自定义方法类

视图组件完毕!

然后,有些东西是需要看源码才能看懂的,相关的源码查看:

from rest_framework import views
from rest_framework import generics
from rest_framework import mixins
from rest_framework import viewsets

  

整个逻辑示图:

前后端分离djangorestframework——视图组件的更多相关文章

  1. 前后端分离djangorestframework——路由组件

    在文章前后端分离djangorestframework——视图组件 中,见识了DRF的视图组件强大,其实里面那个url也是可以自动生成的,就是这么屌 DefaultRouter urls文件作如下调整 ...

  2. 前后端分离djangorestframework——分页组件

    Pagination 为什么要分页也不用多说了,大家都懂,DRF也自带了分页组件 这次用  前后端分离djangorestframework——序列化与反序列化数据  文章里用到的数据,数据库用的my ...

  3. 前后端分离djangorestframework——认证组件

    authentication 认证是干嘛的已经不需要多说.而前后端未分离的认证基本是用cookie或者session,前后端分离的一般用token 全局认证 先创建一个django项目,项目名为drf ...

  4. 前后端分离djangorestframework——ContentType组件表

    ContentType ContentType其实django自带的,但是平时的话很少会用到,所以还是放在Djangorestframework这个部分 作用: 在实际的开发中,由于数据库量级大,所以 ...

  5. 前后端分离djangorestframework——权限组件

    权限permissions 权限验证必须要在认证之后验证 权限组件也不用多说,读了源码你就很清楚了,跟认证组件很类似 具体的源码就不展示,自己去读吧,都在这里: 局部权限 设置model表,其中的ty ...

  6. 前后端分离djangorestframework—— 在线视频平台接入第三方加密防盗录视频

    加密视频 在以后的开发项目中,很可能有做在线视频的,而在线视频就有个问题,因为在线播放,就很有可能视频数据被抓包,如果这个在线视频平台有付费视频的话,这样就会有人做点倒卖视频的生意了,针对这个问题,目 ...

  7. 前后端分离djangorestframework—— 接入第三方的验证码平台

    关于验证码部分,在我这篇文章里说的挺详细的了:Python高级应用(3)—— 为你的项目添加验证码 这里还是再给一个前后端分离的实例,因为极验官网给的是用session作为验证的,而我们做前后端分离的 ...

  8. 前后端分离djangorestframework——序列化与反序列化数据

    我们写好后端的代码,要把数据交给前端的展示的,这个数据以什么类型给前端呢?学到这里,我们已经知道这个数据最好是json字符串才行,因为网络间的传输,只认字符串或者二进制,字符串就是我们的数据,二进制就 ...

  9. 前后端分离djangorestframework——restful规范

    restful现在非常流行,所以很有必要提一下 web服务交互 在浏览器中能看到的每个网站,都是一个web服务.那么我们在提供每个web服务的时候,都需要前后端交互,前后端交互就一定有一些实现方案,我 ...

随机推荐

  1. Unity教程之-UGUI美术字体的制作与使用

    文章转载自:http://www.unity.5helpyou.com/3211.html 游戏制作中,经常需要使用各种花哨的文字或者数字,而字体库往往不能达到我们需要的效果,因此需要一种用图片替代文 ...

  2. 在Mac下连接阿里云服务器

    1.登录 ssh root@IP地址 eg:00.00.00.00 2.新建用户 useradd -d /home/用户名 -m 根目录名 (这条命令,就是创建一个新用户,并给该用户在home目录下创 ...

  3. Linux软件包管理之RPM命令

    目录 1.Linux软件包分类 一.源码包 二.二进制包 2.rpm 包命名规则 3.rpm包安装 4.rpm包升级 5.rpm包卸载 6.查询rpm包是否安装 7.查询软件包的详细信息 8.查询软件 ...

  4. es6入门4--promise详解

    可以说每个前端开发者都无法避免解决异步问题,尤其是当处理了某个异步调用A后,又要紧接着处理其它逻辑,而最直观的做法就是通过回调函数(当然事件派发也可以)处理,比如: 请求A(function (请求响 ...

  5. transform:scale()妙用——当下拉列表,图片无缝拉升 动画效果

      遇到问题 昨天在做音乐播放器的时候,遇到了一个这样的界面: 当下拉scroll区域列表的时候,图片会按照比例无缝连接放大,就想下面的效果图一样 分析问题 从上图可一看到,页面主要由两个div组成, ...

  6. Effective Java——(一)创建和销毁对象

    第一条 考虑用静态工厂方法代替构造器 什么叫静态工厂方法,就是通过在类中通过静态方法对对象初始化. 比如说 public class StaticFactory { private String na ...

  7. @Html.xxxxxFor() 规范写法

    @Html.TextBoxFor() 讲解(其他类似的 @Html.LabelFor 等)同理 @Html.TextBoxFor(model => model.SearchParams.Name ...

  8. Message": "请求的资源不支持 http 方法“GET”

    今天用postman测试后端api,总是报错,下面是问题解决方案. 一.测试方法 public ApiResult Get(int id){ApiResult result = new ApiResu ...

  9. Java中的方法重载与方法重写

    重载(overload) 重载是在一个类中,同名方法拥有不同的参数列表则视为重载.不同的参数列表包括:参数数量不同,参数类型不同,参数顺序不同.重载对于返回类型没有要求,所以不能通过返回类型去判断是否 ...

  10. Exception in thread "main" java.lang.NoClassDefFoundError: org/apache/hadoop/fs/CanUnbuffer

    在执行spark on hive 的时候在  sql.show()处报错 : Exception in thread "main" java.lang.NoClassDefFoun ...