3

I’m still learning django and assume this may be easy for some. I’m trying to figure out the best way of simply setting up the API URLs (and so that they all display in the api root and can actually be used in the project - in my case at /api/). I’m using django rest framework, and can’t seem to set up more than one API - it works for just one, but the problem occurs when trying to set up another.

So I have an app called pages and accounts (and core - the default where the main urls.py is). I’ve created another urls.py inside the pages app and another inside the accounts app.

accounts/urls.py:

from . import views
from rest_framework.routers import DefaultRouter

router = DefaultRouter()
router.register(r"accounts", views.AccountsViewSet, basename="accounts")
urlpatterns = router.urls

pages/urls.py:

from . import views
from rest_framework.routers import DefaultRouter

router = DefaultRouter()
router.register(r"pages", views.PagesViewSet, basename="pages")
urlpatterns = router.urls

And the core urls.py:

from django.contrib import admin
from django.urls import path, include
from rest_framework import routers
from rest_framework.routers import DefaultRouter

router = routers.DefaultRouter()

urlpatterns = [
    path("admin/", admin.site.urls),
    path("api/", include("pages.urls")), # works but root only shows pages API
    # path("api/", include("pages.urls", "accounts.urls")), # fails with error: “django.core.exceptions.ImproperlyConfigured: Specifying a namespace in include() without providing an app_name is not supported. Set the app_name attribute in the included module, or pass a 2-tuple containing the list of patterns and app_name instead.”
    # path("api/", include(router.urls)), # no error but root api is empty
]

I would assume, possibly incorrectly, that just router.urls should include all the apis when visiting the root. The root apis currently looks like this when using just include("pages.urls”):

{
    "pages": "http://localhost:8000/api/pages/"
}

How can I get it to correctly show all apis? The only way I could do it was by putting router.register(r"accounts", views.AccountsViewSet, basename="accounts”) in the pages urls.py, which is very undesirable, especially as the project grows even further.

Thank you

user8758206
  • 2,106
  • 4
  • 22
  • 45

1 Answers1

1

Have you tried to use:

    path("api/pages/", include("pages.urls")),
    path("api/accounts/", include("accounts.urls")),

In your urls.py?

Possibly that would mean your routes would be:

{
     "pages": "http://localhost:8000/api/pages/pages/"
     "accounts": "http://localhost:8000/api/accounts/accounts/"
}

In that case you could try to use

router.register("", views.AccountsViewSet, basename="accounts")

in accounts/urls.py.

And similarly,

router.register("", views.AccountsViewSet, basename="pages")

in pages/urls.py.

That way, you might achieve to have routes like:

{
     "pages": "http://localhost:8000/api/pages/"
     "accounts": "http://localhost:8000/api/accounts/"
}

if that is what you want.

cavalcantelucas
  • 1,362
  • 3
  • 12
  • 34
  • Interesting suggestion, thank you, but this way means that there's no valid /api endpoint that shows all api endpoints. Also in the pages and accounts urls.py files I would only be able to add 1 endpoint since the other one is "". Is there not another way of doing so? Also, shouldn't it be able to use `include(router.urls)`? – user8758206 Dec 30 '21 at 09:13