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/api
andmysite/app2/api
, or - can I have a single api at
mysite/api
which 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
router
or theurls
in 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
urls
modules do not need to be the same as theurls
for standard views.