12_05、路由组件
1、自动生成路由的源码分析
# 只要继承ViewSetMixin 及其子类,路由写法就变了 # 视图类:继承ViewSetMixin,路由写法变了--->而且视图类中的方法不一定写成get,post..,可以随意命名,只不过定义路由时写法变成了path('test/', views.TestView.as_view({'get': 'login'})),get请求执行login方法 # 到底如何执行的? # ViewSetMixin必须写在前面 ViewSetMixin--》as_view--->类的查找顺序---》actions就是传入的字典---》view闭包函数 def view(request, *args, **kwargs): # get login for method, action in actions.items(): # 把login方法的内存地址给了handler handler = getattr(self, action) # 通过反射,设置给get---》对应login---》get请求执行get方法,现在get方法变成了login方法 setattr(self, method, handler) return self.dispatch(request, *args, **kwargs)# 跟之前一样了
2、继承ModelViewSet的路由写法
# 视图类,继承ModelViewSet,路由写法 path('publish/', views.PublishView.as_view({'get':'list','post':'create'})), path('publish/<int:pk>', views.PublishView.as_view({'get':'retrieve','put':'update','delete':'destroy'})) # 到现在,咱们有了一种方式,可以在一个视图类中写很多方法,通过路由的配置,实现一个视图函数对应很多路由 # 上面的两个路由,可以自动生成--->生成上面那两条地址 第一步:导入drf提供的路由类 from rest_framework.routers import SimpleRouter 第二步:实例化得到对象 router = SimpleRouter() 第三步:注册路由 router.register('地址', 视图类, '别名') router.register('publish', views.PublishView, 'publish') 第四步:在urlpatterns加入(两种方式) path('/api/v1', include(router.urls)) urlpatterns+=router.urls
3、SimpleRouter和DefaultRouter
SimpleRouter和DefaultRouter 用法完全一样,只是生成的路由不一样,DefaultRouter比SimpleRouter多一条根地址,一般咱们就用SimpleRouter就可以
4、如果使用自动生成路由,必须继承谁及其子类?
# 如果使用自动生成路由,必须继承谁及其子类? GenericViewSet+5个视图扩展类至少之一---》才能自动生成 ModelViewSet ReadOnlyModelViewSet
5、action装饰器
# action装饰器 -只要是继承ViewSetMixin视图类中方法,都可以加action装饰器,只要加了,自动生成路由会多生成--》127.0.0.1:8080/test/login:get或post都能触发 @action(methods=['GET','POST'],detail=False) def login(self,request): # 如果写法如下,生成的路径是127.0.0.1:8080/test/数字/login @action(methods=['GET','POST'],detail=True) def login(self,request):
6、路由的三种写法
# 以后路由写法有三种 path('books/<int:pk>', views.BookDetailView.as_view()), # 继承了ViewSetMixin path('publish/', views.PublishView.as_view({'get':'list','post':'create'})) # 自动生成路由 from rest_framework.routers import SimpleRouter,DefaultRouter router = SimpleRouter() router.register('publish', views.PublishView, 'publish') # 路由注册,两种方式 path('api/v1/', include(router.urls)), urlpatterns+=router.urls # 路由类,有连个SimpleRouter,DefaultRouter,DefaultRouter自动生成的路由更多
7、补充:可以通过action判断,重写get_queryset,get_serializer_class
class TestView2(GenericViewSet): queryset = Book.objects.all() serializer_class = BookSerializer def get_queryset(self): # 根据请求地址,返回的get_queryset不一样 if self.action=='login': return Author.objects.all() else: return self.queryset def get_serializer_class(self): if self.action=='login': return AuthorSerialzier else: return BookSerializer @action(methods=['GET','POST'],detail=True) def login(self,request): obj=self.get_queryset() return Response("get-login") @action(methods=['GET'], detail=True) def test1(self,request): obj = self.get_queryset() return Response("get-test1")
【推荐】国内首个AI IDE,深度理解中文开发场景,立即下载体验Trae
【推荐】编程新体验,更懂你的AI,立即体验豆包MarsCode编程助手
【推荐】抖音旗下AI助手豆包,你的智能百科全书,全免费不限次数
【推荐】轻量又高性能的 SSH 工具 IShell:AI 加持,快人一步
· Manus爆火,是硬核还是营销?
· 终于写完轮子一部分:tcp代理 了,记录一下
· 别再用vector<bool>了!Google高级工程师:这可能是STL最大的设计失误
· 震惊!C++程序真的从main开始吗?99%的程序员都答错了
· 单元测试从入门到精通