文章目录
一、路由Routers
对于视图集ViewSet,我们除了可以自己手动指明请求方式与动作action之间的对应关系外,还可以使用Routers来帮助我们快速实现路由信息。
REST framework提供了两个router
- SimpleRouter
- DefaultRouter
使用方法: 在urls.py中定义路由
from rest_framework.routers import DefaultRouter
# 定义视图集的路由
router = DefaultRouter()
router.register(r'books',new_views.BookInfoViewSet,base_name='book')
# 将试图集的路由添加到urlpattens
urlpatterns += router.urls
或
from rest_framework import routers
router = routers.SimpleRouter()
router.register(r'books', BookInfoViewSet, base_name='book')
register(prefix, viewset, base_name)
- prefix 该视图集的路由前缀
- viewset 视图集
- base_name 路由名称的前缀
如上述代码会形成的路由如下:
^books/$ name: book-list
^books/{pk}/$ name: book-detail
添加路由数据
可以有两种方式:
urlpatterns = [
...
]
urlpatterns += router.urls
或
urlpatterns = [
...
url(r'^', include(router.urls))
]
工作常见问题总结
提交表单报错:RuntimeError: You called this URL via POST, but the URL doesn’t end in a slash and you have A
原因分析:
RuntimeError: You called this URL via POST, but the URL doesn’t end in a slash and you have APPEND_SLASH set.
提示form的action地址最后不是/结尾的,而且APPEND_SLASH的值是Ture
解决方法:
将from的action地址改为/结尾的就可以了
或者
修改settings:APPEND_SLASH=False
got an unexpected keyword argument ‘pk‘
view层代码
def destroy(self,request, asset_id):
logger.info('delete asset_id: %s' % asset_id)
问题说明:
前端请求/api/v1/asset/857/,发现报错:
TypeError: destroy() got an unexpected keyword argument ‘pk’
ERROR Internal Server Error: /api/v1/asset/857/
不能打印出来 asset_id
问题分析:
这种错误我现在发现有两种可能造成它的出现: 1. url 和 urls.py中的映射不匹配 2. 在views.py中相应的处理函数缺少参数
解决方案:
修改view层代码,把自己写的 asset_id,改成pk
def destroy(self,request, pk):
logger.info('delete asset_id: %s' % pk)
说明这里只能写成pk!
二、action装饰器
视图集中附加action的声明
action装饰器可以接收两个参数:
- methods: 声明该action对应的请求方式,列表传递
- detail: 声明该action的路径是否与单一资源对应,及是否是xxx//action方法名/
- True 表示路径格式是xxx//action方法名/
- False 表示路径格式是xxx/action方法名/
from rest_framework.decorators import action
# 追加action:返回书记的倒叙地0个书籍的信息
@action(methods=['get'],detail=False)
def latest(self, request):
"""
# 追加action 修改图书的阅读数量
@action(methods=['put'],detail=True)
def read(self, request, pk):
"""
@action 只在ViewSet视图集中生效
@action 装饰器用于在 ViewSet 中创建自定义动作(custom action),这些动作可以是不同于标准 CRUD 操作(创建、检索、更新和删除)的自定义端点。它为 ViewSet 提供了更灵活的方式来定义额外的端点。
@action装饰器是ViewSet专有的,它可以在ViewSet视图集上添加额外的自定义行为,从而丰富ViewSet的功能。
ViewSet的子类同样支持使用@action装饰器添加自定义动作。这是因为ViewSet的子类会继承ViewSet的路由机制,所以也可以将使用@action添加的动作加载到URL conf中。
APIView不是ViewSet的子类,不支持@action
总结:@action装饰器只适用于ViewSet视图集,在APIView或其子类上不会生效。
APIView或其子类,自定义路由以添加自定义的URL映射
对于APIView或其子类,自定义路由以添加自定义的URL映射。您可以使用Django框架提供的URL配置来实现。因为@action不能用了!!!
在APIView中,可以通过两种方式将不同的URL映射到不同的方法上:
- 根据URL的请求方法,Django会自动将请求映射到对应的APIView方法上。如:
class ExampleView(APIView):
def get(self, request):
...
def post(self, request):
...
url(r'^example/$', ExampleView.as_view(), name='example')
- GET /example/请求会调用ExampleView的get()方法
- POST /example/请求会调用post()方法
- 使用URL的名称关键字参数来明确指定所调用的方法。如:
url(r'^example/get/$', ExampleView.as_view(name='get'), name='example-get')
url(r'^example/post/$', ExampleView.as_view(name='post'), name='example-post')
class ExampleView(APIView):
name = 'get'
def get(self, request):
...
name = 'post'
def post(self, request):
...
- GET /example/get/会调用name='get’的方法
- POST /example/post/会调用name='post’的方法
所以,总结来说,在APIView中有两种方式可以将URL映射到不同的视图方法上:
- 依靠URL的请求方法,Django会自动进行映射。
- 使用name关键字参数明确指定所要调用的视图方法。
这两种方式可以单独使用,也可以结合使用。前者适用于典型的CRUD场景,后者更加灵活。
三、路由router形成URL的方式(URL路径参数)
1) SimpleRouter
2)DefaultRouter
DefaultRouter与SimpleRouter的区别是,DefaultRouter会多附带一个默认的API根视图,返回一个包含所有列表视图的超链接响应数据。
URL路径参数使用示例demo:
DELETE:/V1.0/xxx/asset/2738df11-7376-4f3b-a179-69b14f307d78
我们要在views.py 对2738df11-7376-4f3b-a179-69b14f307d78 参数进行获取。
四、总结
- 一般我们使用SimpleRouter就行。
- @action 的detail 其中的pk 是视图方法参数
- True 表示路径格式是xxx//action方法名/
- False 表示路径格式是xxx/action方法名/
视图层方法demo:
@action(methods=['post'], detail=True)
def delete_token(self, request, pk):
token = Tokens.objects.get(id=pk)
token.delete()
return Response("删除成功")
五、参考
Django-路由Routers-SimpleRouter-DefaultRouter的使用
参考URL: https://blog.csdn.net/Odyssues_lee/article/details/80896033