My DRF routers specify a namespace so that I can reverse
my urls:
urls.py:
router = DefaultRouter()
router.register('widget/', MyWidgetViewSet, base_name='widgets')
urlpatterns =+ [
url(r'/path/to/API/', include(router.urls, namespace='widget-api'),
]
Which, when upgrading to django 2, gives:
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.
Django 2 now requires app_name
if the namespace
kwarg is specified when using include
. What's the right way to specify app_name
when the url patterns are constructed by a DRF url router? I don't think the documentation is up-to-date for django 2 on this subject.
You need to put app_name = 'x'
in your application's url.py
file. This is a little buried in the documentation:
https://docs.djangoproject.com/en/2.0/topics/http/urls/#id5
For example, if in /project/project/urls.py
you have:
path('', include('app.urls', namespace='app'))
Then in the corresponding url file (in /project/app/urls.py
) you need to specify the app_name
parameter with:
app_name = 'app' #the weird code
urlpatterns = [
path('', views.index, name = 'index'), #this can be anything
]
You need to include the router.urls as a tuple and add the app name to the tuple instead of only include router.urls
According to your example you should try with something like:
router = DefaultRouter()
router.register('widget/', MyWidgetViewSet, base_name='widgets')
urlpatterns =+ [
url(r'/path/to/API/', include((router.urls, 'my_app_name'), namespace='widget-api'),
]
The recommended approach is
from django.conf.urls import url, include
from rest_framework import routers
router = routers.DefaultRouter()
router.register(r'widget/', MyWidgetViewSet)
urlpatterns = [
url(r'^path/to/API/', include('rest_framework.urls', namespace='widget-api'))
]
See http://www.tomchristie.com/rest-framework-2-docs/tutorial/quickstart#urls
It's just necessary to use '{basename}-list' in reverse function.
In your case, it's going to be: reverse('widgets-list')