How to register DRF router url patterns in django

2020-02-14 03:25发布

问题:

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.

回答1:

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
] 


回答2:

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'),
]


回答3:

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



回答4:

It's just necessary to use '{basename}-list' in reverse function.
In your case, it's going to be: reverse('widgets-list')