Django · DRF ViewSet视图集,再次简化,让你彻底解放双手,开发RESTful接口!

DRF入门-ViewSet

1. 前言

之前我们使用普通的或者封装的APIView开发接口时,总是需要分两类情况处理

  1. 有主键 /user/20/ (id=20的用户)
  2. 无主键 /user/ (实现get所有或者post创建)

我们总是需要分两种接口去写,然后还要进行两次类的封装,其实代码的冗余还是比较高,那有没有办法,直接写一个类就能实现呢?

ViewSet类就是DRF给我们的解决方案!

2. ViewSet引入

2.1 ViewSet能实现什么?

其实ViewSet实现的,就是让我们原本必须按照规定,定义的post/get/delete方法,可以随心所欲的进行定义,不再需要必须起那个名字

比如,我希望我的函数名这样起,这样他就能实现一个类满足有无主键的两种需求

from rest_framework.viewsets import ViewSet # 导入ViewSet
class BookViewSet(ViewSet):
    """
    	继承ViewSet
    """
    def get_all_data(self, request): # 对应get无pk方法(查询多个)
        return Response('返回所有书籍')

    def create_data(self, request): # 对应post创建方法
        return Response('创建一个书籍')

    def get_one_data(self, request, pk): # 对应get有pk方法(查询单个)
        return Response(f'返回pk={pk}的书籍')

    def update_data(self, request, pk): # 对应put/patch有pk更新方法
        return Response(f'更新pk={pk}的书籍')

    def delete_date(self, request, pk): # 对应delete有pk删除
        return Response(f'删除pk={pk}的书籍')

所以我们只要按这个思路去走,就能够再次简化原本的代码!

但是,我们光进行定义,程序也不知道POST/GET到底该去调用哪个方法

对于定义了ViewSet的类,我们需要在路由中传入as_view()方法的时候传入字典!

传入格式:

“请求方法名”:“实际执行的函数名”

urls.py

from django.urls import path,re_path
from BookManage.views import *
urlpatterns = [    path("booknew/<int:pk>/",BookView.as_view({"get":"get_one_data","delete":"delete_date","put":"update_data"})),
 # 对于有pk的,我们 get -> get_one_data | delete -> delete_date | put -> update_data
 path("booknew/",BookView.as_view({"get":"get_all_data","post":"create_data"})),
 # 对于没有pk的,get -> get_all_data | post -> create_data
]

此时我们进行请求就可以发现,使用一个类就可以完成两种接口的请求。

GET http://127.0.0.1:8000/booknew/1/
---> "返回pk=1的书籍"
DELETE http://127.0.0.1:8000/booknew/1/
---> "删除pk=1的书籍"

GET http://127.0.0.1:8000/booknew/ # 无pk
---> "返回所有书籍"

3. ModelViewSet引入

3.1 ModelViewSet源码解析

其实ViewSet与APIView类似,他也有对应的GenericViewSet,并且也支持继承Mixin

所以为了我们的方法便,这里直接引入ModelViewSet

其实ModelViewSet本质上就是帮我们继承了所有的Mixins,让我们只需要在定义路由的时候,分别定义不同的方法就够了!

ModelViewSet源码:

class ModelViewSet(mixins.CreateModelMixin,
                   mixins.RetrieveModelMixin,
                   mixins.UpdateModelMixin,
                   mixins.DestroyModelMixin,
                   mixins.ListModelMixin,
                   GenericViewSet):
    # 它就是帮我们把五种Mixins全部继承,并且继承了GenericViewSet
    # GenericViewSet和我们的GenericAPIView几乎一样,就是多了可以自定义不同方法使用哪个函数
    pass

所以使用ModelViewSet后,我们可以直接把之前用两个类定义的代码,拿过来换成一个类,然后直接重新写一个路由即可!

使用ModelViewSet定义之前的BookListView和BookDetailView

3.2 案例实现

views.py类定义

from rest_framework.viewsets import ModelViewSet
class BookViewSet(ModelViewSet):
    queryset = Book.objects.all()
    serializer_class = BookSerializer

    def get_all_data(self, request):  # 对应get无pk方法(查询多个)
        return self.list(request)

    def create_data(self, request):  # 对应post创建方法
        return self.create(request)

    def get_one_data(self, request, pk):  # 对应get有pk方法(查询单个)
        return self.retrieve(request)

    def update_data(self, request, pk):  # 对应put/patch有pk更新方法
        return self.update(request)

    def delete_date(self, request, pk):  # 对应delete有pk删除
        return self.destroy(request)

urls.py定义路由

from django.urls import path,re_path
from BookManage.views import *
urlpatterns = [    	path("booknew/<int:pk>/",BookView.as_view({"get":"get_one_data","delete":"delete_date","put":"update_data"})),
	path("booknew/",BookView.as_view({"get":"get_all_data","post":"create_data"})),
]

请求结果示例:

GET http://127.0.0.1:8000/booknew/2/
{
	"id": 2,
	"name": "嫌疑人X的现身",
	"pub_date": "2006-10-03",
	"author": {
		"id": 2,
		"name": "东野圭吾",
		"introduce": "东野圭吾(ひがしの けいご,Higashino Keigo),1958年2月4日出生于日本大阪,日本推理小说作家,毕业于大阪府立大学电气工学专业,之后在汽车零件供应商日本电装担任生产技术工程师。代表作有《放学后》《秘密》《白夜行》《以眨眼干杯》《神探伽利略》《嫌疑人X的献身》《预知梦》《湖畔》等。"
	},
	"price": "40.00"
}

4. 路由再次简化!

虽然我们这样非常方便,但是我们每次去定义路由的时候,都要去把定义的路由重新写一大串,非常的啰嗦,麻烦!

DRF封装了视图集(ModelView)配合他的路由route,可以让我们把双手彻底解放掉!!

urls.py创建默认路由

from rest_framework import routers # 导入路由函数
route = routers.DefaultRouter() # 创建路由
route.register('book', viewset=BookView)
# 注册路由,viewset是我们创建的ViewSet视图(必须是继承自viewset/派生类的视图,不能是APIView)
# 注册的第一个参数填写名称即可
# 填写book则会关联 /book/ 以及 /book/<pk>/

urlpatterns = []
urlpatterns += route.urls # 将创建的路由添加到列表




--------也可以这样--------


urlpatterns = [
    path('',include(route.urls)), # 用include进行路由分发,可以用到名称空间
]

这时候我们定义下ViewSet即可

from rest_framework.viewsets import ModelViewSet
class BookViewSet(ModelViewSet):
    queryset = Book.objects.all()
    serializer_class = BookSerializer
	......
    # 下面啥也不用写,只要继承了 ModelViewSet,就不用管了!
    # 除非需要自定义其他请求!

就这么简单,我们一个接口的开发就完成了!

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值