DRF--重写views(一)

简介: DRF--重写views

前戏


在前面几篇文章里,我们写了get请求,post请求,put请求,在来写个delete请求,大概如下。

class BookView(APIView):  # 查询所有的数据和post方法
    def get(self, request):
        book_queryset = Book.objects.all()
        # 拿出来的是一个queryset,用序列化器进行序列化
        ser_obj = BookSerializer(book_queryset, many=True)
        return Response(ser_obj.data)  # 序列化后的数据在data里
    def post(self, request):
        # 确定数据类型以及数据结构
        # 对前端传来的数据进行校验
        book_obj = request.data  # post传来的数据
        ser_obj = BookSerializer(data=book_obj)  # 有data参数,表示反序列化
        if ser_obj.is_valid():
            ser_obj.save()
            return Response(ser_obj.validated_data)
        return Response(ser_obj.errors)  # 返回错误
class BookEditView(APIView):  # 查询单条数据和put、delete方法
    def get(self, request, id):
        book_obj = Book.objects.filter(id=id).first()
        ser_obj = BookSerializer(book_obj)  # 查询出的是一条数据,不需要加 many=True
        return Response(ser_obj.data)
    def put(self, request, id):
        book_obj = Book.objects.filter(id=id).first()
        # instance必传,data=request.data前端传的参数,partial=True部分修改
        ser_obj = BookSerializer(instance=book_obj, data=request.data, partial=True)
        if ser_obj.is_valid():
            ser_obj.save()
            return Response(ser_obj.data)  # 返回数据,注意不是ser_obj.validated_data
        return Response(ser_obj.errors)
    def delete(self, request, id):
        book_obj = Book.objects.filter(id=id).first()
        if not book_obj:
            return Response('删除的对象不存在')
        book_obj.delete()
        return Response('Success')

路由

urlpatterns = [
    url(r'^book/$', BookView.as_view()),
    url(r'^book/(?P<id>\d+)', BookEditView.as_view()),
]

 

这个视图只是实现了Book表的增删改查功能,如果有几十张表,我们就要写几十个对应的类,复制,粘贴,复制,粘贴。。。身为一个优秀的测试工程师。这种比较low的方法肯定不是我们干的,应该是开发干的,手动滑稽。

如果分析上面的代码,我们会发现,每个请求只要传不同的ORM语句和序列化器就可以实现了。所以我们可以对代码进行重构,面向对象的三大特性,继承,封装,多态。我们可以写一个通用的方法来继承它,每个子类都可以改写继承过来的方法,就是多态。


第一版


1 from django.shortcuts import render
 2 from rest_framework.views import APIView
 3 from rest_framework.response import Response
 4 from djangoDemo.models import Book  # 导入表
 5 from .serializers import BookSerializer
 6
 7
 8 class GenericAPIView(APIView):  # 通用的API视图
 9     queryset = None
10     serializer_class = None
11
12     def get_queryset(self):
13         # 这里要加.all() 虽然下面的ORM查询出来的是所有的数据
14         # 但是由于DRF的内部机制,这里如果不加就会报错
15         return self.queryset.all()
16
17     def get_serializer(self, *args, **kwargs):
18         # 不同请求的序列化器里传的参数是不一样的
19         return self.serializer_class(*args, **kwargs)
20
21
22 class BookView(GenericAPIView):  # 继承通用的方法
23     queryset = Book.objects.all()
24     serializer_class = BookSerializer
25
26     def get(self, request):
27         # 调用外部的get方法
28         queryset = self.get_queryset()
29
30         # 调用外部的序列化方法
31         ser_obj = self.get_serializer(queryset, many=True)
32         return Response(ser_obj.data)
33
34     def post(self, request):
35         ser_obj = self.get_serializer(data=request.data)
36         if ser_obj.is_valid():
37             ser_obj.save()
38             return Response(ser_obj.validated_data)
39         return Response(ser_obj.errors)

当上面的代码执行get请求时,先执行28行,28行调用的是12,执行15行,返回的是一个queryset,然后先在自己内部找,自己内部有,也就是23行,在执行31行,调用的是17行,执行19行,返回的是serializer_class,先在自己内部找,自己内部有,也就是24行。在执行32行

上面的代码只是简单的封装了一下,还可以在次封装。


第二版


1 from django.shortcuts import render
 2 from rest_framework.views import APIView
 3 from rest_framework.response import Response
 4 from djangoDemo.models import Book  # 导入表
 5 from .serializers import BookSerializer
 6
 7
 8 class GenericAPIView(APIView):  # 通用的API视图
 9     queryset = None
10     serializer_class = None
11
12     def get_queryset(self):
13         # 这里要加.all() 虽然下面的ORM查询出来的是所有的数据
14         # 但是由于DRF的内部机制,这里如果不加就会报错
15         return self.queryset.all()
16
17     def get_serializer(self, *args, **kwargs):
18         # 不同请求的序列化器里传的参数是不一样的
19         return self.serializer_class(*args, **kwargs)
20
21 class ListModelMixin(object):  # get方法,查询所有数据
22     def list(self, request):
23         queryset = self.get_queryset()
24         ser_obj = self.get_serializer(queryset, many=True)
25         return Response(ser_obj.data)
26
27 class CreateModelMixin(object):  # post方法
28     def create(self, request):
29         ser_obj = self.get_serializer(data=request.data)
30         if ser_obj.is_valid():
31             ser_obj.save()
32             return Response(ser_obj.validated_data)
33         return Response(ser_obj.errors)
34
35
36 class BookView(GenericAPIView, ListModelMixin, CreateModelMixin):  # 继承
37     queryset = Book.objects.all()
38     serializer_class = BookSerializer
39
40     def get(self, request):
41         return self.list(request)  # 调用get方法
42
43     def post(self, request):
44         return self.create(request)  # 调用post方法

上面对BookView类进行了封装处理,还有一个BookEditView类,也来进行封装处理

from django.shortcuts import render
from rest_framework.views import APIView
from rest_framework.response import Response
from djangoDemo.models import Book  # 导入表
from .serializers import BookSerializer
class GenericAPIView(APIView):  # 通用的API视图
    queryset = None
    serializer_class = None
    def get_queryset(self):
        # 这里要加.all() 虽然下面的ORM查询出来的是所有的数据
        # 但是由于DRF的内部机制,这里如果不加就会报错
        return self.queryset.all()
    def get_serializer(self, *args, **kwargs):
        # 不同请求的序列化器里传的参数是不一样的
        return self.serializer_class(*args, **kwargs)
class RetrieveModelMixin(object):  # get方法,查询单条数据
    def retrieve(self, request, id):
        # 先查询出所有,在过滤,在取第一个
        book_obj = self.get_queryset().filter(id=id).first()
        ser_obj = self.get_serializer(book_obj)
        return Response(ser_obj.data)
class UpdateModelMixin(object):  # put方法
    def update(self, request, id):
        book_obj = self.get_queryset().filter(id=id).first()
        ser_obj = self.get_serializer(instance=book_obj, data=request.data, partial=True)
        if ser_obj.is_valid():
            ser_obj.save()
            return Response(ser_obj.data)  # 返回数据,注意不是ser_obj.validated_data
        return Response(ser_obj.errors)
class DestroyModelMixin(object):  # delete方法
    def destoy(self, request, id):
        book_obj = self.get_queryset().filter(id=id).first()
        if not book_obj:
            return Response('删除的对象不存在')
        book_obj.delete()
        return Response('Success')
class BookEditView(GenericAPIView, RetrieveModelMixin, UpdateModelMixin, DestroyModelMixin):  # 查询单条数据和put、delete方法
    queryset = 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.destoy(request, id)

这样我们就完成了所有请求的封装

在来看下,每个BookView类和BookEditView类都继承了好几个类,如果以后还有其他的类,都要继承这几个类,多麻烦,我们可以写两个单独的类,来继承,以后所有的类都继承这两个类就可以了


相关文章
|
9月前
|
前端开发 安全 API
DRF--介绍和安装
DRF--介绍和安装
|
2天前
|
存储 JSON 数据格式
Spartacus i18n Resource 的默认加载和 Lazy Load 两种方式的比较
Spartacus i18n Resource 的默认加载和 Lazy Load 两种方式的比较
21 0
|
9月前
|
Python
|
9月前
|
Python
DRF--view
DRF--view
|
10月前
|
网络架构 Python
【Django学习】(十四)自定义action_router
【Django学习】(十四)自定义action_router
|
缓存
Laravel-admin 重写源码 自定义排序回调
有几个业务相关的配置信息需要管理后台灵活配置,且返回的数据要进行排序 为了保证业务接口的请求速度,我们把这些配置信息接口做了缓存 在管理后台进行form表单提交的时候清空缓存,保证数据及时更新(比如删除、修改之后要刷新缓存) 测试阶段发现一个问题,laravel-admin 的 sortable 扩展和框架本身的form表单提交没有关系,执行排序的时候没有回调函数,导致排序操作后无法主动清除缓存。
303 0
Laravel-admin 重写源码 自定义排序回调
|
存储 缓存 NoSQL
【Django学习笔记 - 8】:session的配置和使用、类视图初使用
【Django学习笔记 - 8】:session的配置和使用、类视图初使用
305 0
【Django学习笔记 - 8】:session的配置和使用、类视图初使用
|
缓存 资源调度
[项目篇]vue3+ts 封装request请求,storage缓存,config请求信息抽离 - 第二天
[项目篇]vue3+ts 封装request请求,storage缓存,config请求信息抽离 - 第二天
SAP Spartacus lazy load module 里包含了被其他 Component 静态引用的组件该怎么办
SAP Spartacus lazy load module 里包含了被其他 Component 静态引用的组件该怎么办
87 0
SAP Spartacus lazy load module 里包含了被其他 Component 静态引用的组件该怎么办
|
Python
Django的rest_framework的视图之Mixin类编写视图源码解析
Django的rest_framework的视图之Mixin类编写视图源码解析 Mixin类编写视图 我们这里用auther表来做演示,先为auther和autherdetail写2个url 1 2 url(r'^autherdetail/(?P\d+)', views.
1393 0