使用django-rest-framework我正在使用 DefaultRouter
我想为几个应用程序提供API,所以我的问题是我可以用django方式执行此操作并将我的路由器注册放在每个应用程序URLconf中,并将它们显示为一个聚合API或理想情况下以命名空间方式显示.
换句话说,如果app1
包含modelA
和modelB
,则app2
包含modelC
:
我可以声明出现在mysite/app1/api
和的两个路由器mysite/app2/api
,或者
我可以在一个api中mysite/api
列出所有三个模型,然后在他们自己的应用程序中注册各个模型urls.py
就像是
router = DefaultRouter() router.register(r'users', views.UserViewSet) router.register(include('app1.apis') router.register(include('app2.apis')
或者有一种简单的方法,我的路由器变量可以在每个应用程序的URLconf中可用,以便他们可以调用router.register
?我不确定
urlpatterns = patterns('', url(r'^snippets/', include('snippets.urls', namespace="snippets")) ... url(r'^api/', include(router.urls)),
实际上导致代码在app1/urls.py
该点执行,以便它可以router.register
以某种方式调用,以便最终的url调用包括所有应用程序注册以及项目注册.
UPDATE
使用Nicolas Cortot的变体option 2
我得到了我的特定资源API
,但它没有被列为root API
at 的可用资源myserver\api\
我假设以某种方式DefaultRouter
创建它自己的页面定义并向其router.register
添加条目.我当前的设置(我认为Nicholas的选项1)也创建了两个独立的路由器,只有一个可以显示为服务器根目录,下面的设置myserver\api\
列出users
但不是片段.
这是我目前的设置:
project urls.py:
router = DefaultRouter() router.register(r'users', views.UserViewSet) urlpatterns = patterns('', url(r'^admin/', include(admin.site.urls)), url(r'^api/', include(router.urls)), url(r'^api/', include('snippets.apiurls')), url(r'^api-auth/', include('rest_framework.urls', namespace='rest_framework')), )
项目/段/ apiurls.py:
router = DefaultRouter() router.register(r'snippets', views.SnippetViewSet) urlpatterns = patterns('', url(r'^', include(router.urls)), )
如果我将项目中条目的顺序颠倒urls.py
为:
url(r'^api/', include('snippets.apiurls')), url(r'^api/', include(router.urls)),
然后我被snippets
列出但不是users
我猜Django正在服务第一条匹配路线.
除非有人能告诉我,否则我似乎需要传递一个路由器变量并以某种方式添加.
两种选择都是可能的.您可以公开router
或urls
在每个应用程序中,并将它们合并到您的全局urls
.我通常更喜欢使用urls
(选项2),因为它在每个应用程序中提供了更大的灵活性:您可以根据需要定义额外的非api URL.
在你的全球urls.py中:
from app1.api.routers import router1 from app2.api.routers import router2 urlpatterns = patterns('', url(r'^snippets/', include('snippets.urls', namespace="snippets")) ... url(r'^app1/api/', include(router1.urls)), url(r'^app2/api/', include(router2.urls)), )
您可以轻松地为两个路由器使用相同的端点(只要您注意不要使用冲突的路由):
urlpatterns = patterns('', url(r'^snippets/', include('snippets.urls', namespace="snippets")) ... url(r'^api/', include(router1.urls)), url(r'^api/', include(router2.urls)), )
在appN/api/urls.py中:
router = DefaultRouter() router.register(r'users', views.UserViewSet) router.register(include('app1.apis') urlpatterns = patterns('', url(r'^', include(router.urls)), url(r'^misc/', some_other_view), )
在你的全球urls.py中:
urlpatterns = patterns('', url(r'^snippets/', include('snippets.urls', namespace="snippets")) ... url(r'^api/', include('app1.api.urls')), url(r'^api/', include('app2.api.urls')), )
请注意,urls
模块不需要与urls
标准视图相同.
通过绕过单个路由器实例,如下是可能的。
router.py
在您的main
项目文件夹中创建一个名为或类似文件:
from rest_framework import routers common_router = routers.DefaultRouter()
在每个应用程序的位置urls.py
:
from main.router import common_router as router router.register(r'myapp-model-name', MyAppViewSet)
在您的内容中main
urls.py
:
import my_app1.urls # to register urls with router import my_app2.urls # to register urls with router ... # finally import router that includes all routes from main.router import common_router urlpatterns = [ ... url(r'^api/', include(common_router.urls)), ... ]
要在同一个API根目录中获取所有应用程序,您需要使用相同的DefaultRouter注册所有应用程序.
实现此目的的一种方法是创建一个自定义路由器,它拦截寄存器调用并将其传播到共享路由器.然后,您可以使用此共享路由器来获取API.
class SharedAPIRootRouter(SimpleRouter): shared_router = DefaultRouter() def register(self, *args, **kwargs): self.shared_router.register(*args, **kwargs) super().register(*args, **kwargs) # if not py3: super(SharedAPIRootRouter, self).register(*args,**kwargs)
然后在每个应用程序:
# in app1/urls.py router = SharedAPIRootRouter() router.register(r'app1', App1ModelViewSet) # in app2/urls.py router = SharedAPIRootRouter() router.register(r'app2', App2ModelViewSet)
在您的主urls.py中,您必须确保导入应用程序URL,以便在我们请求shared_router.urls之前进行注册
import app1.urls import app2.urls def api_urls(): return SharedAPIRootRouter.shared_router.urls urlpatterns = patterns( '', url(r'^api/', include(api_urls())), )
如果您不想显式导入网址,可以按惯例执行:
def api_urls(): from importlib import import_module for app in settings.INSTALLED_APPS: try: import_module(app + '.urls') except (ImportError, AttributeError): pass return SharedAPIRootRouter.shared_router.urls