Django · DRM Mixin混合类,三行代码让你实现RESTful接口一键部署!

本文介绍了DRFMixin如何通过插件机制封装GET、POST等操作,降低开发复杂度。通过Mixin,如AuthorListView和AuthorDetailView示例展示了如何使用ListCreateAPIView和RetrieveUpdateDestroyAPIView来简化接口开发,同时强调了其适用场景和潜在局限性。
摘要由CSDN通过智能技术生成

DRF Mixin功能引入

在了解Mixin插件前,我们必须先了解什么是Mixin,具体可见这个文章
Mixin机制介绍

Mixin机制的引入,可以大大解放我们的双手,因为DRF通过Mixin已经帮我们把GET/POST/PUT…各种请求完全封装完成!

1. DRF - Mixin做了什么

Mixin其实就是一个插件功能,并且脱离于所有的子类数据,比如我们想给鸭子加一个游泳,给狗加一个游泳功能,那就创建一个SwimMixin,只要让雷继承于这个SwimMixin,就能实现游泳功能,DRF中也是类似的。

需求分析:

这是我们之前使用GenericAPIView实现的接口,尽管已经非常简洁

但是,里面的get方法我们还是要自己去get_serializer,POST还是要自己去save等等,还是比较麻烦

class BookListView(GenericAPIView):
    queryset = Book.objects.all()
    serializer_class = BookSerializer

    def get(self, request):
        """
        	GET里面的ORM操作还是有些繁琐,需要自己去获取
        """
        # self.get_serializer ---> 返回的就是 serializer_class实例化对象
        serializer = self.get_serializer(instance=self.get_queryset(), many=True)
        return Response(serializer.data)

    def post(self, request):
        """
        	POST也要写一大堆东西才能save
        """
        serializer = self.get_serializer(data=request.data)
        if serializer.is_valid():
            serializer.save()
            return Response(serializer.data)
        else:
            return Response(serializer.errors, status=status.HTTP_201_CREATED)

DRF中的Mixin直接为我们提供了 增删查改的各种方法,下面是一个使用Mixin的案例

2. 使用Mixin实现AuthorListView

from rest_framework.mixins import CreateModelMixin, UpdateModelMixin, ListModelMixin, RetrieveModelMixin,DestroyModelMixin
class AuthorListView(CreateModelMixin, ListModelMixin, GenericAPIView):
    """
    	因为ListView需要使用两种方式:
    		1.get请求获取全部数据
			2.post创建数据    	
		所以,直接继承CreateModelMixin(创建数据插件),ListModelMixin(列表模型插件)
    """
    queryset = Author.objects.all()
    serializer_class = AuthorSerializer

    def get(self, requset):
        """
        	使用了Mixin,我们直接返回一个self.list就可以
        """
        return self.list(requset)

    def post(self, request):
        # 直接返回self.create就是实现了我们的创建数据
        return self.create(request)

2.1 Mixin源码解析,为什么直接返回list/create就行

POST -> CreateModelMixin源码

class CreateModelMixin:
    """
    Create a model instance. 
    翻译: 创建一个模型示例
    """
    def create(self, request, *args, **kwargs):
    	"""
    		其实可以看到,这里的实现,和我们之前自己去create是类似的
    		所以其实就是帮我们直接把创建的方法封装起来了
    	"""
        serializer = self.get_serializer(data=request.data)
        serializer.is_valid(raise_exception=True)
        self.perform_create(serializer)
        headers = self.get_success_headers(serializer.data)
        # 最后返回的就是一个Response
        return Response(serializer.data, status=status.HTTP_201_CREATED, headers=headers)

GET -> ListModelMixin源码

class ListModelMixin:
	"""
		ListModelMixin和我们之前自己写的GET也是非常类似
	"""
    def list(self, request, *args, **kwargs):
        queryset = self.filter_queryset(self.get_queryset())

        page = self.paginate_queryset(queryset)
        if page is not None:
            serializer = self.get_serializer(page, many=True)
            return self.get_paginated_response(serializer.data)

        serializer = self.get_serializer(queryset, many=True)
        return Response(serializer.data)

2.2 Mixin有哪些?

DRF中的Mixins都存放在rest_framework.mixins库中

from rest_framework.mixins import CreateModelMixin, UpdateModelMixin, ListModelMixin, RetrieveModelMixin,DestroyModelMixin
  1. CreateModelMixin 创建数据的Mixin(一般对应POST请求)

    —> 返回 self.create(request) 即可

  2. ListModelMixin 获取多个数据的Mixin(对应GET请求无主键id的情况)

    —> 返回 self.list(request) 即可

  3. UpdateModelMixin更新数据的Mixin(对于PUT/PATCH请求)

    —> 返回 self.update(request) 即可

  4. RetrieveModelMixin 获取单个数据的Mixin(对应GET请求有主键id的情况)

    ----> 返回 self.retrieve(request) 即可

  5. DestroyModelMixin 删除数据的Mixin(对应DELETE请求)

    ----> 返回 self.destroy(request) 即可

2.3 Mixin案例

以下是基于Mixin实现的完整案例:

AuthorListView是对应POST和GET无主键id的请求

AuthorDetailView对应其他请求和GET有id请求

class AuthorListView(CreateModelMixin, ListModelMixin, GenericAPIView):
    queryset = Author.objects.all()
    serializer_class = AuthorSerializer

    def get(self, requset):
        return self.list(requset)

    def post(self, request):
        return self.create(request)


class AuthorDetailView(DestroyModelMixin, RetrieveModelMixin, UpdateModelMixin, GenericAPIView):
    queryset = Author.objects.all()
    serializer_class = AuthorSerializer

    def get(self, requset,pk):
        return self.retrieve(requset)

    def delete(self, request,pk):
        return self.destroy(request)

    def put(self, request,pk):
        return self.update(request)

3. Mixins + APIView混合使用

上面的虽然已经非常非常的简易了,但是其实可以发现,我们每次写的时候,还是有很多重复的地方

  1. 每次都得继承一大堆东西,太长了
  2. 每次都得定义下get/post/put…但是里面逻辑都一样,完全没必要

!!而DRF考虑我们懒人需求,所以就增加了Mixins和APIVies混用的封装!!!

我们现在这里明白需求,我们的同一个请求接口,其实对应两种情况

  1. 路由传参有pk参数(有主键ID) -> GET多个/PUT/PATCH/DELETE
  2. 没有pk参数(无主键ID) -> POST创建/GET单个

所以,其实,就是分成了两种类,一种类是有 GET/POST并且不需要pk

另一种类就是有GET/DELETE/PUT还得要pk

而DRF为我们直接将这两种情况分别封装出来!

from rest_framework.generics import ListCreateAPIView
from rest_framework.generics import RetrieveUpdateDestroyAPIView

3.1 ListCreateAPIView类

看名字就能看出来,他是一个包含创建+List返回的APIView,那么我们看看他的源码是什么样

class ListCreateAPIView(mixins.ListModelMixin,
                        mixins.CreateModelMixin,
                        GenericAPIView):
    """
    	其实一眼就可以看出来,他就是帮我们继承了两个Mixin还有GenericAPIView
    	然后帮我们写个get和post
    """
    def get(self, request, *args, **kwargs):
        return self.list(request, *args, **kwargs)

    def post(self, request, *args, **kwargs):
        return self.create(request, *args, **kwargs)

所以,ListCreateAPIView其实就是帮我们做了我们觉得麻烦的事情,有了 它以后,我们的代码再次简化!

class AuthorListView(ListCreateAPIView):
    """
        好了,就这三行代码,让你把一个视图写完了!
    """
    queryset = Author.objects.all()
    serializer_class = AuthorSerializer

就这么简单,So Easy的实现了你的接口!!

3.2 RetrieveUpdateDestroyAPIView类

这和3.1一样,一眼看出来,就是查询单个/更新/删除+APIView的封装类

说白了就是PUT/PATCH啥的,我们也不用写了,直接继承完事儿

继承后的代码如下:

class AuthorDetailView(RetrieveUpdateDestroyAPIView):
    """
        还是三行代码,带你又完成了一个接口!
    """
    queryset = Author.objects.all()
    serializer_class = AuthorSerializer

现在,我两个ORM对应的视图,一共20行代码,就完成了接口部分的开发,我们只需要去专注于Model和序列化器就够了!

3.3 其他问题!

现在有小朋友问了,万一我这个接口,我不想要PATCH,老板说这个多余,不要这个,怎么办

有没有什么快速解决办法??

必须有啊,我们首先要明白,为什么RetrieveUpdateDestroyAPIView能直接帮我们直接把三个全部实现了,是因为人家源码中继承了3个

那你自己直接继承两个不就完事儿了??PATCH的那个你直接不要了就实现了需求!

但是!!!DRF帮我们写好了!

  1. RetrieveUpdateAPIView : 只有更新和查询单个,没有删除
  2. RetrieveAPIView :只有查询单个,连更新都没有
  3. UpdateAPIView : 只有更新,没有删除和查询
  4. 以此类推,全部都支持,想怎么换怎么换!!

4. 重要提醒

虽然这样写非常的爽,十几行代码完成了你所有的需求,但是!!!!

我们这样写出来的代码可定制度实在太低,如果要实现其他额外的需求,这些写就不够用了

这种只适用于标准接口的开发,而复杂逻辑的开发,还是需要用到基类APIView

APIView我在前面的文章也有讲过,他是实现这些高级封装类的基础类

只有看明白了APIView,才能高度定制自己的Django应用

5. 后续还能够简化代码,使用ViewSet,让我们只需要定义一个类,就能完成有主键和无主键两种接口的开发!具体见后续文章,没有看过基础的简易看看我之前的文章!

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值