路由是如何映射的?

2022-05-09 18:30:58 浏览数 (1)

目录

  • DRF 路由组件
    • 路由是如何映射的?
    • 继承ModelViewSet,路由写法
      • 自己配路由的映射
      • 自动生成路由
    • action装饰器
      • 继承APIView ViewSetMixin使用装饰器
    • 路由router形成URL的方式

DRF 路由组件

路由的配置上篇我们提到了一点自动配置,对于继承了视图集ViewSet就可以自动生成路由,当然了也可以选择手动版自己配,可以使用action装饰器来指定方法等操作,屁话不多说如下:

REST framework提供了两个router

  • SimpleRouter
  • DefaultRouter

路由组件使用,如果视图类继承了ViewSetMixin及其子类,那么路由写法可以改变,而且视图类中的方法也可以自定制,不一定是get,post,可以随意命名

代码语言:javascript复制
from rest_framework.views import APIView
from rest_framework.viewsets import ViewSetMixin
from rest_framework.response import Response
class TestView(ViewSetMixin,APIView):
    def login(self,requets):
        return Response('test-login')
代码语言:javascript复制
# 路由
path('test/',views.TestView.as_view({'get': 'login'}))

注意

继承的时候,如果继承了ModelViewSet就相当于继承了ViewSetMixin的子类了,不需要继承ViewSetMixin了,不然会报错

代码语言:javascript复制
class BookView(ModelViewSet):
    queryset = models.Book.objects.all()
    serializer_class = serializer.BookSerializer
代码语言:javascript复制
path('books/', views.BookView.as_view({'get':'list'})),

路由是如何映射的?

代码语言:javascript复制
1、ViewSetMixin写在前面
2、先走ViewSetMixin的as_view
        if not actions:
            raise TypeError("The `actions` argument must be provided when "
                            "calling `.as_view()` on a ViewSet. For example "
                            "`.as_view({'get': 'list'})`")
4、如果actions不传就报错,也就是as_view()内不写字典就报错
5、view闭包函数
 def view(request, *args, **kwargs):
            self = cls(**initkwargs)
		····
	for method, action in actions.items():
        '''method:get     action:login'''
        # 把login方法的内存地址给了handler
        handler = getattr(self, action)
        # 通过反射,设置给get---》对应login---》get请求执行get方法,现在get方法变成了login方法
        setattr(self, method, handler)
      return self.dispatch(request, *args, **kwargs)# 跟之前一样了

继承ModelViewSet,路由写法

ModelViewSet继承了五个扩展类 GenericViewSet,提供了相应的接口方法增删改查

代码语言:javascript复制
from rest_framework.viewsets import ModelViewSet
class BookView(ModelViewSet):
    queryset = models.Book.objects.all()
    serializer_class = serializer.BookSerializer

自己配路由的映射

代码语言:javascript复制
 path('books/', views.BookView.as_view({'get':'list','post':'create'})),
path('books/<int:pk>', views.BookView.as_view({'get':'retrieve','put':'update','delete':'destroy'}))

自动生成路由

代码语言:javascript复制
from rest_framework.routers import SimpleRouter

from app01 import views

router = SimpleRouter()
router.register('books', views.BookView, 'books')
urlpatterns = [
path('api/v1/', include(router.urls)),
 ]
'''
或者不写path('api/v1/', include(router.urls)),写下面的
urlpatterns  = router.urls
'''

action装饰器

只要是继承ViewSetMixin视图类或其子类,都可以加action装饰器

导入rest_framework.decorators.action

参数

  • methods:请求方法,列表的形式写
  • detail:是否带id,True不带id,False带id
  • url_path:地址,地址如果不写,默认已方法名为地址
  • url_name:起别名

继承APIView ViewSetMixin使用装饰器

代码语言:javascript复制
from rest_framework.decorators import action
class TestView(ViewSetMixin,APIView):
    @action(methods=['GET','POST'],detail=False)
    def login(self,requets):
        return Response('test-login')
代码语言:javascript复制
from rest_framework.routers import SimpleRouter
from app01 import views

router1 = SimpleRouter()
router1.register('test',views.TestView,'test')
urlpatterns = [
 path('aip/v2/', include(router1.urls)),
]

'''
http://127.0.0.1:8000/aip/v2/test/login/
'''

注意

如果这样写detail=True,路由就成了http://127.0.0.1:8000/aip/v2/test/1/login/,数字的部分一般为pk

最后都是路由前缀拼接一个方法名

路由router形成URL的方式

1) SimpleRouter

2)DefaultRouter

DefaultRouter与SimpleRouter的区别是,DefaultRouter会多附带一个默认的API根视图,返回一个包含所有列表视图的超链接响应数据

总结

路由的写法有三种:

  • 手动配置:path('books/<int:pk>', views.BookDetailView.as_view())
  • 继承ViewSetMixin,使用action属性:views.PublishView.as_view({'get':'list','post':'create'}))
  • 使用SimpleRouter或DefaultRouter自动生成(两种方式):
代码语言:javascript复制
router = SimpleRouter()

router.register('books', views.PublishView, 'books')

urlpatterns = [

path('api/v1/', include(router.urls)),

]

# 或者

urlpatterns = [

urlpatterns =router.urls

]
  • DefaultRouter比SimpleRouter多一层根路径

0 人点赞