sea*_*olf 51 django django-rest-framework
我有一个跨多个应用程序的项目:
./project/app1
./project/app2
./project/...
Run Code Online (Sandbox Code Playgroud)
每个应用程序都有一个Django REST Framework路由器,可以整合该应用程序提供的API部分:
from django.conf.urls import url, include
from rest_framework.routers import DefaultRouter
from .views import ThingViewSet
router = DefaultRouter()
router.register(r'things', ThingViewSet, base_name='thing')
urlpatterns = [
url(r'^', include(router.urls)),
]
Run Code Online (Sandbox Code Playgroud)
由于应用是独立的,因此我的顶级网址file(./project/urls.py)包含来自不同应用的每个网址文件:
url(r'^api/app1/', include('app1.urls', namespace='a1')),
url(r'^api/app2/', include('app2.urls', namespace='a2')),
Run Code Online (Sandbox Code Playgroud)
这意味着Django REST Framework为每个应用程序显示一个单独的API根目录.但是,我想要的是一个统一的API结构,因此,如果我导航到http://example.com/api/我,我会看到该层次结构中所有可用URL的完整列表.
我认为有一种方法可以将urls.py每个应用程序的单个文件中定义的所有单独路由器包含在一个路由器中,但是我找不到有关如何执行此操作的文档.我错过了一些明显的东西吗
小智 39
另一种解决方案是SimpleRouter用于为各个应用定义路由器.然后,使用自定义DefaultRouter包含应用程序特定路由.这样,所有特定于应用程序的URL定义都将保留在相应的应用程序中.
假设您有两个名为"app1"和"app2"的应用程序,每个应用程序都有一个名为"api"的目录,并且在此目录中有一个名为"urls"的文件,其中包含您的所有路径定义.
??? project/
? ??? api_urls.py
? ??? app1
? ? ??? api
? ? ? ??? urls.py
? ??? app2
? ? ??? api
? ? ? ??? urls.py
? ??? patches
? ? ??? routers.py
用于patches/router.py定义名称DefaultRouter继承自的类rest_framework.routers.DefaultRouter.
from rest_framework import routers
class DefaultRouter(routers.DefaultRouter):
"""
Extends `DefaultRouter` class to add a method for extending url routes from another router.
"""
def extend(self, router):
"""
Extend the routes with url routes of the passed in router.
Args:
router: SimpleRouter instance containing route definitions.
"""
self.registry.extend(router.registry)
Run Code Online (Sandbox Code Playgroud)
用路线定义填写你的api url
"""
URL definitions for the api.
"""
from patches import routers
from app1.api.urls import router as app1_router
from app2.api.urls import router as app2_router
router = routers.DefaultRouter()
router.extend(app1_router)
router.extend(app2_router)
Run Code Online (Sandbox Code Playgroud)
sha*_*rey 15
这将获取基本API URL上列出的所有ViewSet路由.
它将路由定义为相应包含的app.urls中的列表,以便可以在其他地方注册.
将它们包含在基本urls.py中之后,构建嵌套的列表列表并循环遍历以在API中注册同一级别的所有路由
# foo.urls
routeList = (
(r'foos', FooViewSet),
)
# barBaz.urls
routeList = (
(r'bars', BarViewSet),
(r'bazs', BazViewSet),
)
# urls
from rest_framework import routers
from foo import urls as fooUrls
from barBaz import urls as barBazUrls
routeLists = [
fooUrls.routeList,
barBazUrls.routeList,
]
router = routers.DefaultRouter()
for routeList in routeLists:
for route in routeList:
router.register(route[0], route[1])
Run Code Online (Sandbox Code Playgroud)
结果:
{
"foo": "http://localhost:8000/foos/",
"bar": "http://localhost:8000/bars/",
"baz": "http://localhost:8000/bazs/",
}
Run Code Online (Sandbox Code Playgroud)
这也减少了每个文件的重复次数,并且可以说更容易阅读.
此外,它仍然完全解耦.
如果在其他地方使用了包含的app,则可以在内部使用相同的方法来注册它自己的路由,而不必包含在任何地方.
只需放下外部循环
routeList = (
(r'bars', BarViewSet),
(r'bazs', BazViewSet),
)
router = routers.DefaultRouter()
for route in routeList:
router.register(route[0], route[1])
Run Code Online (Sandbox Code Playgroud)
@科尔顿·希克斯评论
假设“apps 文件夹”中有 2 个应用程序(权限、用户)。然后我们可以这样做:
from apps.users.api.urls import router as users_router
from apps.permissions.api.urls import router as permissions_router
router = DefaultRouter()
router.registry.extend(users_router.registry)
router.registry.extend(permissions_router.registry)
Run Code Online (Sandbox Code Playgroud)
我最终创建了一个URL文件,其中包含urls_api_v1.py所需的所有路由:
router = DefaultRouter()
router.register(r'app1/foos', FooViewSet, base_name='foo')
router.register(r'app2/bars', BarViewSet, base_name='bar')
router.register(r'app2/bazs', BazViewSet, base_name='baz')
Run Code Online (Sandbox Code Playgroud)
作为一个副作用,这使我能够摆脱每个应用程序中的所有个人urls.py文件,这些文件通常是您需要的,但在这种情况下,整个应用程序集合需要统一的URL结构,因此删除更为明智.
然后我引用它urls.py:
import api_v1
urlpatterns = patterns('',
...,
url(r'^api/v1/', include(api_v1, namespace='api-v1')),
)
Run Code Online (Sandbox Code Playgroud)
现在,如果我想更改v2的路由,我也可以包含一个v2 URL文件,并最终弃用v1文件.
您可以使用router.registry.extend(app_router.registry),总示例:
from django.urls import path, include
from rest_framework import routers
from app1.rest import router as app1_router
from app2.rest import router as app2_router
router = routers.DefaultRouter()
router.registry.extend(app1_router.registry)
router.registry.extend(app2_router.registry)
urlpatterns = [
path('', include(router.urls)),
]
Run Code Online (Sandbox Code Playgroud)
| 归档时间: |
|
| 查看次数: |
10772 次 |
| 最近记录: |