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
:
mysite/app1/api
and mysite/app2/api
, ormysite/api
which lists all three models yet register the individual models in their own app's urls.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.
API permissionsChoose Add a permission, and under Microsoft APIs, select Microsoft Graph, and then select Delegated permissions. Add the following permissions: User. Read - allows your application to sign-in your user.
Sign in to the Azure portal. If you have access to multiple tenants, use the Directories + subscriptions filter in the top menu to select the tenant containing your client app's registration. Select Azure Active Directory > App registrations, and then select your API's app registration.
Conclusion. Azure App registrations are an easy and powerful way to configure authentication and authorization workflows for a variety of different client types. Everything from Android to a SAML application can be configured to use an app registration.
Expose API means this app represents the API you need to access. API Permission means this app will be used to make requests to web API app or Microsoft Graph resources.
To get all apps in the same API root, you need to register all your apps with the same DefaultRouter.
One way to achieve this is to make a custom router, which intercepts the register call and propagates it to a shared router. You then use this shared router to get the api urls.
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)
Then in each app:
# in app1/urls.py
router = SharedAPIRootRouter()
router.register(r'app1', App1ModelViewSet)
# in app2/urls.py
router = SharedAPIRootRouter()
router.register(r'app2', App2ModelViewSet)
In your main urls.py, you must ensure you import the app urls so that registration occurs before we ask for 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())),
)
if you do not want to import the urls explicitly, you can do it by convention:
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
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With