Django REST framework(九)-视图集ViewSet、GenericViewSet、ModelViewSet、ReadOnlyModelViewSet_simpleyako的博客-CSDN博客
对于上次学到的视图集来说,虽然我们在编写视图逻辑代码时通过继承ModelViewSet后只需提供序列化器和模型对象查询集即可省去增删改查(查询所有数据)这五个常用的接口大量的代码。但是我们在编写路由时,又有些许的麻烦,所有drf为我们提供了routers路由集,为我们在编写视图代码继承视图集时提供自动生成路由的功能。
如下图是继承视图集ModelViewSet后编写的代码及路由。
class _ModelViewSet(ModelViewSet):
queryset = BookInfo.objects.all()
serializer_class = BookSerializer
#
# --------------------ModelViewSet-----------------------------------------
path('demo/books/', _ModelViewSet.as_view({
'get': 'list',
'post': 'create'
})),
re_path(r'^demo/books/(?P\d+)/$', _ModelViewSet.as_view({
"get": 'retrieve',
'delete': 'destroy',
'put': 'update'
})),
对于视图集,我们除了可以自己手动指明请求方式与动作action(视图名)之间的对应关系外,还可以使用Routers来帮助我们快速实现路由信息。如果是非视图集,不需要使用路由集routers
from rest_framework.routers.DefaultRouter
如下:通过DefaultRouter自动生成路由步骤(默认自动生成list、create、delete、update、retrieve五个视图函数的路由):
# -------------------DefaultRouter-----------------------------------------
from rest_framework.routers import DefaultRouter
# 1.实例化DefaultRouter路由对象
routers = DefaultRouter()
# 2.指定继承视图集的视图,自动生成路由
routers.register('demo/books', _ModelViewSet, basename='demo/books/')
for url in routers.urls:
print(url)
# 3.将生成的路由添加到urlpatterns中去
urlpatterns += routers.urls
"""
1、对应创建模型对象和查询所有模型对象数据的路由
2、对应更改、查询、删除单个模型对象的路由
[a-z0-9]+)/?$' [name='demo/books/-list']>
[^/.]+)/$' [name='demo/books/-detail']>
[^/.]+)\.(?P[a-z0-9]+)/?$' [name='demo/books/-detail']>
3、对应访问url路径http://127.0.0.1:8000时显示
{
"demo/books": "http://127.0.0.1:8000/demo/books/"
}
4、对应访问url路径http://127.0.0.1:8000\时显示
{
"demo/books": "http://127.0.0.1:8000/demo/books/"
}
[a-z0-9]+)/?$' [name='api-root']>
"""
对应根路径的路由
对应更改、查询、删除单个模型对象路径的路由
对应创建模型对象和查询所有模型对象数据的路径路由
使用方式与DefaultRouter一致的。只是少两个根目录url路径以及将四个url路径压缩为两个。
# -------------------SimpleRouter-----------------------------------------
from rest_framework.routers import SimpleRouter
# 1.实例化DefaultRouter路由对象
routers = SimpleRouter()
# 2.指定继承视图集的视图,自动生成路由
routers.register('demo/books', _ModelViewSet, basename='demo/books/')
for url in routers.urls:
print(url)
# 3.将生成的路由添加到urlpatterns中去
urlpatterns += routers.urls
1、对应创建模型对象和查询所有模型对象数据的路由
2、对应更改、查询、删除单个模型对象的路由
[^/.]+)/$' [name='demo/books/-detail']>
缺少的根路径路由
1、对应创建模型对象和查询所有模型对象数据的路由
2、对应更改、查询、删除单个模型对象的路由
rest_framework.decorators.action
在视图集中,如果想要让Router自动帮助我们自定义出除开(list、create、delete、update、retrieve)这五个视图函数的url路由外的路由,因为可能一个视图中不止这些方法。则我们需要在视图集中使用action装饰器。
以action装饰器装饰的视图函数方法名会作为action动作名,与list、retrieve等同。
action装饰器可以接收两个参数:
methods: 声明该action对应的请求方式,列表参数
detail: 声明该action的路径是否与单一资源对应
路由前缀//action方法名/
True 表示路径格式是xxx/
False 表示路径格式是xxx/action方法名/
url_path:声明该action的路由尾缀。
代码
class _ModelViewSet(ModelViewSet):
def get_serializer_class(self):
if self.action == 'get_books_name':
return BookNameSerializer
else:
return BookSerializer
queryset = BookInfo.objects.all()
@action(methods=['GET'], detail=False)
def get_books_name(self, request):
names = self.get_queryset()
ser = self.get_serializer(instance=names, many=True)
return Response(data=ser.data)
自动生成的路由
其中自动生成的后缀路由get_books_name/就是视图函数名,demo/books/为以下生成视图集路由时的前缀
routers.register('demo/books', _ModelViewSet, basename='demo/books/')
如果想后缀名/login不是由自动生成路由时的函数名,可以通过url_path自定义后缀名
class _ModelViewSet(ModelViewSet):
def get_serializer_class(self):
if self.action == 'get_books_name':
return BookNameSerializer
else:
return BookSerializer
queryset = BookInfo.objects.all()
@action(methods=['GET'], detail=False, url_path='get_name')
def get_books_name(self, request):
names = self.get_queryset()
ser = self.get_serializer(instance=names, many=True)
return Response(data=ser.data)
代码
from rest_framework.decorators import action
from .Serializer import BookNameSerializer
class _ModelViewSet(ModelViewSet):
def get_serializer_class(self):
if self.action == 'get_books_name':
return BookNameSerializer
else:
return BookSerializer
queryset = BookInfo.objects.all()
@action(methods=['GET'], detail=True, url_path='get_name')
def get_books_name(self, request, pk):
names = self.get_object()
ser = self.get_serializer(instance=names)
return Response(data=ser.data)
自动生成的路由
[^/.]+)/get_name/$' [name='demo/books/-get-books-name']>