django 路由
SimpleRouter
1 2 3 4 5
| from rest_framework.routers import SimpleRouter
router = SimpleRouter() router.register(r'users', UserViewSet)
|
register 有三个参数
- prefix(必需) 此组路由的url前缀
- viewset(必需) 处理请求的viewset类
- base_name(可选) 如果视图集不包括queryset属性,那么在注册视图集时必须设置base_name也就是viewset 没有自定义model 或 get_queryset方法时,必须填写此属性
生成的路由
- URL pattern: ^users/$ Name: ‘user-list’
- URL pattern: ^users/{pk}/$ Name: ‘user-detail’
在路由中的使用
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21
| router = routers.SimpleRouter() router.register(r'users', UserViewSet) router.register(r'accounts', AccountViewSet)
urlpatterns = [ url(r'^forgot-password/$', ForgotPasswordFormView.as_view()), ]
urlpatterns += router.urls
urlpatterns = [ url(r'^forgot-password/$', ForgotPasswordFormView.as_view()), url(r'^', include(router.urls)), ]
urlpatterns = [ url(r'^forgot-password/$', ForgotPasswordFormView.as_view()), url(r'^api/', include(router.urls, namespace='api')), ]
|
额外连接和操作
用@detail_route或@list_route装饰的视图集上的任何方法也将被路由
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17
| class TestViewSet(viewsets.ViewSet): permission_classes = []
from rest_framework.decorators import detail_route, list_route @action(methods=['get'], detail=False) def latest(self, request): ... @action(methods=['put'], detail=True) def read(self, request, pk): ... @detail_route(methods=['get'], url_path='zb')
|
自定义组名和正则
1 2 3
| class MyModelViewSet(mixins.RetrieveModelMixin, viewsets.GenericViewSet): lookup_field = 'my_model_id' lookup_value_regex = '[0-9a-f]{32}'
|
额外的action
我们知道, viewset里面我们可以通过继承不同的mixins来实现列表,详情,增加,修改,部分修改,删除种不同功能的接口。
可是在实际情况中,我们需要的不仅仅是这些,所以,我们需要额外的url来路由。于是引入了action装饰器,我们可以在viewset中添加额外的路由了,使用方法:
在之前旧的版本使用的是detail_route,list_route连个装饰器来添加额外的路由,用来区别url中是否有pk字段。action装饰器则是通过detail字段来区别
1 2 3 4 5 6 7 8
| from myapp.permissions import IsAdminOrIsSelf from rest_framework.decorators import action
class UserViewSet(ModelViewSet): ...
@action(methods=['post'], detail=True, permission_classes=[IsAdminOrIsSelf]) def set_password(self, request, pk=None):
|
使用上面action生成的url是 ^users/{pk}/set_password/$。 如果不想使用方法的名字来做路由,可以在action中指定url_name。
ExtendedDefaultRouter
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31
| from rest_framework_extensions.routers import ExtendedDefaultRouter
router.register(r'/we_chat', WeChatPayViewSet, 'we_chat')
class WeChatPayViewSet(viewsets.ViewSet): permission_classes = (IsAuthenticated,)
@action(methods=["POST"], is_for_list=True) def app_pay(self, request, *args, **kwargs):
# 当viewset使用@action时 class TestViewSet(viewsets.ViewSet):
model = EStoreOrder
@action(methods=['GET']) def test(self, request, *args, **kwargs): return Response('ok')
# 生成的路由为 ^api/estore/test/(?P<pk>[^/.]+)/test/$ [name='estoreorder-test'] ^api/estore/test/(?P<pk>[^/.]+)/test/\.(?P<format>[a-z0-9]+)$ [name='estoreorder-test']
当使用 @action(methods=['GET'], is_for_list=True) 生成的路由为 ^api/estore/test/test/$ [name='estoreorder-test-list'] ^api/estore/test/test/\.(?P<format>[a-z0-9]+)$ [name='estoreorder-test-list']
|
路由router形成URL的方式
SimpleRouter
DefaultRouter