django - 在应用程序中注册 API

标签 django json rest django-rest-framework urlconf

使用 django-rest-framework 我正在使用 DefaultRouter
我想为多个应用程序提供 API,所以我的问题是我能否以 django 方式执行此操作并将我的路由器注册放在每个应用程序 URLconf 中,并让它们显示为一个聚合 api 或理想情况下以命名空间方式显示。

换句话说,如果 app1包含 modelAmodelB , 而 app2包含 modelC :

  • 我可以声明出现在 mysite/app1/api 处的 2 个路由器吗?和 mysite/app2/api , 或
  • 我可以在 mysite/api 上有一个 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 调用包括所有应用程序注册以及项目注册。

    更新

    使用 Nicolas Cortot 的变体 option 2我得到我的特定资源 API工作,但它未在 root API 中列为可用资源在 myserver\api\
    我认为不知何故 DefaultRouter创建它自己的页面定义和 router.register添加条目。我当前的设置(我认为 Nicholas 的选项 1 也是如此)创建了两个单独的路由器,只有一个可以显示为服务器根目录,设置如下,myserver\api\列表 users但不是片段。

    这是我目前的设置:

    项目 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 正在服务第一个匹配的路由。

    除非有人能告诉我,否则我似乎需要一个单一的路由器变量来传递并以某种方式添加。

    最佳答案

    要在同一个 API 根中获取所有应用程序,您需要使用相同的 DefaultRouter 注册所有应用程序。

    实现这一点的一种方法是制作一个自定义路由器,它拦截注册调用并将其传播到共享路由器。然后您使用此共享路由器来获取 api url。

    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())),   
    )   
    

    如果您不想显式导入 url,则可以按惯例进行:
    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
    

    关于django - 在应用程序中注册 API,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/20825029/

    相关文章:

    Python 2.6.2,Django 1.0.3,Windows XP,找不到页面 :/

    python - Django 1.8 Duration字段和时差

    javascript - 如何将数据(可能是 JSON)的差异推送到服务器?

    java - Jersey REST 请求对象更改

    java - 抛出异常时 Servlet 过滤器不工作

    node.js - 洞察两种 REST API 设计的可行性

    django - 请求对象没有属性 "accepted_renderer"

    python - 将模型字段数据传递给 Django 中的验证器

    ios - 快速解析嵌套的 JSON 属性

    javascript - Webpack 将 config.js 编译为 config.json