With django-rest-framework I'm using the DefaultRouter
I want to provide APIs to several apps, so my question is can I do this in a django manner and put my router registrations in each app URLconf and have them appear either as one aggregate api or ideally in a namespaced way.
In other words if app1 contains modelA and modelB, while app2 contains modelC:
- can I declare 2 routers that appear at
mysite/app1/apiandmysite/app2/api, or - can I have a single api at
mysite/apiwhich lists all three models yet register the individual models in their own app'surls.py
Something like
router = DefaultRouter()
router.register(r'users', views.UserViewSet)
router.register(include('app1.apis')
router.register(include('app2.apis')
Alternatively is there a simple way in which my router variable can be made available in each app's URLconf so that they can call router.register? I'm not sure if
urlpatterns = patterns('',
url(r'^snippets/', include('snippets.urls', namespace="snippets"))
...
url(r'^api/', include(router.urls)),
actually cause the code in app1/urls.py to be executed at that point so that it could call router.register somehow, so that the final url call includes all the app registrations as well as the project one.
UPDATE
Using a variation on Nicolas Cortot's option 2 I get my specific resource API to work, but it is not listed as an available resource in the root API at myserver\api\
I assume that somehow DefaultRouter creates it's own page definition and router.register adds entries to it. My current setup (and I think Nicholas's option 1 as well) create two separate routers, and only one can get displayed as the server root, with the setup below, myserver\api\ lists users but not snippets.
Here's my current setup:
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')),
)
project/snippets/apiurls.py:
router = DefaultRouter()
router.register(r'snippets', views.SnippetViewSet)
urlpatterns = patterns('',
url(r'^', include(router.urls)),
)
If I reverse the order of the entries in the project urls.py as:
url(r'^api/', include('snippets.apiurls')),
url(r'^api/', include(router.urls)),
then I get snippets listed but not users
I guess Django is serving the first matching route.
Unless someone can tell me otherwise I seem to need a single router variable to be passed around and added to somehow.
Both options are possible. You can either expose the
routeror theurlsin each app, and merge those into your globalurls. I usually prefer usingurls(option 2) because it gives more flexibility in each app: you can define extra non-api URLs as needed.Option 1
In your global urls.py:
You can as easily use the same endpoint for both routers (as long as you're careful not to use conflicting routes):
Option 2
In appN/api/urls.py:
In your global urls.py:
Note that the
urlsmodules do not need to be the same as theurlsfor standard views.