DRF(八):视图集和路由
一 视图集ViewSet
使用视图集ViewSet,可以将一系列逻辑相关的动作放到一个类中:
- list() 提供一组数据
- retrieve() 提供单个数据
- create() 创建数据
- update() 保存数据
- destory() 删除数据
ViewSet视图集类不再实现get()、post()等方法,而是实现动作 action 如 list() 、create() 等。
视图集只在使用as_view()方法的时候,才会将action动作与具体请求方式对应上。
class BookInfoViewSet(viewsets.ViewSet):
def list(self, request):
books = BookInfo.objects.all()
serializer = BookInfoSerializer(books, many=True)
return Response(serializer.data)
def retrieve(self, request, pk=None):
try:
books = BookInfo.objects.get(id=pk)
except BookInfo.DoesNotExist:
return Response(status=status.HTTP_404_NOT_FOUND)
serializer = BookInfoSerializer(books)
return Response(serializer.data)
在设置路由时,我们可以如下操作:
urlpatterns = [
url(r'^books/$', BookInfoViewSet.as_view({'get':'list'}),
url(r'^books/(?P<pk>\d+)/$', BookInfoViewSet.as_view({'get': 'retrieve'})
]
1.1 常用视图集父类
1) ViewSet
继承自APIView
与ViewSetMixin
,作用也与APIView基本类似,提供了身份认证、权限校验、流量管理等。
ViewSet主要通过继承ViewSetMixin来实现在调用as_view()时传入字典(如{‘get’:’list’})的映射处理工作。
在ViewSet中,没有提供任何动作action方法,需要我们自己实现action方法。
2)GenericViewSet
使用ViewSet通常并不方便,因为list、retrieve、create、update、destory等方法都需要自己编写,而这些方法与前面讲过的Mixin扩展类提供的方法同名,所以我们可以通过继承Mixin扩展类来复用这些方法而无需自己编写。但是Mixin扩展类依赖与GenericAPIView
,所以还需要继承GenericAPIView
。
GenericViewSet就帮助我们完成了这样的继承工作,继承自GenericAPIView
与ViewSetMixin
,在实现了调用as_view()时传入字典(如{'get':'list'}
)的映射处理工作的同时,还提供了GenericAPIView
提供的基础方法,可以直接搭配Mixin扩展类使用。
from rest_framework.viewsets import GenericViewSet
from rest_framework.mixins import ListModelMixin,CreateModelMixin,RetrieveModelMixin,UpdateModelMixin,DestroyModelMixin
class Student4ViewSet(GenericViewSet,ListModelMixin,CreateModelMixin,RetrieveModelMixin,UpdateModelMixin,DestroyModelMixin):
queryset = Student.objects.all()
serializer_class = StudentModelSerializer
url的定义
urlpatterns = [
path("students7/", views.Student4ViewSet.as_view({"get": "list", "post": "create"})),
re_path("students7/(?P<pk>\d+)/", views.Student4ViewSet.as_view({"get": "retrieve","put":"update","delete":"destroy"})),
]
3)ModelViewSet
继承自GenericViewSet
,同时包括了ListModelMixin、RetrieveModelMixin、CreateModelMixin、UpdateModelMixin、DestoryModelMixin。
4)ReadOnlyModelViewSet
继承自GenericViewSet
,同时包括了ListModelMixin、RetrieveModelMixin。
1.2 视图集中定义附加action动作
在视图集中,除了上述默认的方法动作外,还可以添加自定义动作。
from rest_framework.viewsets import ModelViewSet,ReadOnlyModelViewSet
class StudentModelViewSet(ModelViewSet):
queryset = Student.objects.all()
serializer_class = StudentModelSerializer
def login(self,request):
"""学生登录功能"""
return Response({"message":"登录成功"})
# url的定义
urlpatterns = [
path("stu/login/",views.StudentModelViewSet.as_view({"get":"login"}))
]
1.3 action属性
在视图集中,我们可以通过action对象属性来获取当前请求视图集时的action动作是哪个。
from rest_framework.viewsets import ModelViewSet
from students.models import Student
from .serializers import StudentModelSerializer
from rest_framework.response import Response
class StudentModelViewSet(ModelViewSet):
queryset = Student.objects.all()
serializer_class = StudentModelSerializer
def get_new_5(self,request):
"""获取最近添加的5个学生信息"""
# 操作数据库
print(self.action) # 获取本次请求的视图方法名
通过路由访问到当前方法中.可以看到本次的action就是请求的方法名
二 路由Routers
三种路由写法
1. path('test/', views.Test.as_view()),
2. path('test/', views.Test.as_view({'get':'send_email'})),
3. 自动生成路由
2.1 自动生成路由
自动生成路由需要视图类继承ViewSet视图集及其子类。我们除了可以自己手动指明请求方式与动作action之间的对应关系外,还可以使用Routers来帮助我们快速实现路由信息。
REST framework提供了两个router
- SimpleRouter
- DefaultRouter
自动生成路由方法
register(prefix, viewset, base_name)
- prefix 该视图集的路由前缀
- viewset 视图集
- base_name 路由别名的前缀
# 1 导入路由类
from rest_framework.routers import SimpleRouter, DefaultRouter
# DefaultRouter生成的路由更多一点,多了一个根的路由(没有用)
# 2 实例化得到对象
router = SimpleRouter()
# 3 注册路由
router.register('books', views.BookView,'book')
urlpatterns = [
# 4 把自动生成的路径加入到urlpatterns
path('api/v1/', include(router.urls)),
path('admin/', admin.site.urls)
]
# 4 把自动生成的路径加入到urlpatterns
# urlpatterns+=router.urls
------------------------------------------------------------------------------------------
------------------------------------------------------------------------------------------
自动生成的路由地址结果
'api/v1/book/' name:book_list
'api/v1/book/pk/' name: book_detail
2.2 视图集中附加action的声明
在视图集中,如果想要让Router自动帮助我们为自定义的动作生成路由信息,需要使用rest_framework.decorators.action
装饰器。
以action装饰器装饰的方法名会作为action动作名,与list、retrieve等同。
action装饰器可以接收两个参数:
-
methods: 声明该action对应的请求方式,列表传递
-
detail: 声明该action的路径是否与单一资源对应,及是否是
- True 表示路径格式是
xxx/<pk>/action方法名/
- False 表示路径格式是
xxx/action方法名/
- True 表示路径格式是
举例:
1 作用:给自动生成路由的视图类再定制一些路由
2 用法一:
# 接口地址api/v1/books/sen_email/
@action(methods=['GET'], detail=False)
def sen_email(self, request, *args, **kwargs):
print(args)
print(kwargs)
return APIResponse(msg='发送成功')
3 方法二:
# 接口地址api/v1/books/1011/sen_email/
@action(methods=['GET'], detail=True)
def sen_email(self, request, *args, **kwargs):
# pk=1011
print(args)
print(kwargs)
return APIResponse(msg='发送成功')
DefaultRouter与SimpleRouter的区别是,DefaultRouter会多附带一个默认的API根视图,返回一个包含所有列表视图的超链接响应数据。
上一篇: Python多线程多进程应用场景