Django 基础(6)-路由Routers-SimpleRouter-DefaultRouter、 action装饰器、URL路径参数

一、路由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映射到不同的方法上:

  1. 根据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()方法
  1. 使用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映射到不同的视图方法上:

  1. 依靠URL的请求方法,Django会自动进行映射。
  2. 使用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

  • 2
    点赞
  • 9
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 2
    评论
评论 2
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

西京刀客

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值