Django DRF с версией API-интерфейса NameSpace.Исправлена ​​ошибка NoReverseMatch или ImproperlyConfigured. - PullRequest
0 голосов
/ 20 декабря 2018

Я хочу создать версию моего API, но не могу заставить работать функцию реверса.

Я следую схеме управления версиями пространства имен, предложенной на веб-сайте DRF: изменение пространства имен

Iу меня есть одно приложение под названием аутентификация и внутри папки аутентификации у меня есть:

 authentication/
 |
  -- models.py, apps.py, admin.py
  -- api_v1/
     |
     -- views.py
     -- serializers.py
     -- urls.py

В моем основном urls.py я определил

urlpatterns = [
    url(r'admin/', admin.site.urls),
    url(r'^api/v1/',include

('my_project.apps.authentication.api_v1.urls',namespace='v1'),
        ('my_project.apps.posts.api_v1.urls',namespace='v1')
     ),
    url(r'^$', lambda _: redirect('http://localhost:8888/')),
]

Это аутентификация/api_v1/urls.py

from rest_framework.routers import DefaultRouter                       

from authentication.api_v1.views import UserViewSet                    

app_name = 'authentication'                                            
router = DefaultRouter()                                               
router.register(r'users', UserViewSet, base_name='authentication-user')

urlpatterns = router.urls                                              

И когда я выполняю

./manage.py show_urls

 /api/v1/users/ authentication.api_v1.views.UserViewSet v1:authentication-user-list
 /api/v1/users/<pk>/    authentication.api_v1.views.UserViewSet v1:authentication-user-detail

Когда я пытаюсь вернуться, например, из оболочки, у меня появляется следующая ошибка:

> reverse('v1:authentication-user-detail', kwargs={'pk': '5'})

NoReverseMatch: Reverse for 'authentication-user-detail' not found. 'authentication-user-detail' is not a valid view function or pattern name.

> reverse('authentication:v1:posts-job-detail', kwargs={'pk': '5'})

NoReverseMatch: 'v1' is not a registered namespace inside 'authentication'

> reverse('v1:authentication:posts-job-detail', kwargs={'pk': '5'})

NoReverseMatch: 'authentication' is not a registered namespace inside 'v1'

НО, если я не добавлю namespace = 'v1' в URL-адреса приложения, например:

url(r'^api/v1/',include('my_project.apps.authentication.api_v1.urls')

Тогда обратные функции будут работать

> reverse('authentication:authentication-user-detail', kwargs={'pk':5})
> '/api/v1/users/5/'

Я думаю, что янеправильно называю реверс или, может быть, какая-то конфигурация?Потому что, если я вызываю API, например, через почтальона, конечная точка работает нормально.

ОБНОВЛЕНИЕ:

Я думаю, что проблема в том, что у меня одинаковое пространство имен для двух записей вмой главный urls.py я опоздаю.Я думаю, что решение состоит в том, чтобы иметь только одну запись в моих основных URL-адресах и переместить все остальные в другой файл.

ОБНОВЛЕНИЕ 2

Я думаю (я не уверенесли это правильно) я заставляю это работать так.В моем основном urls.py

api_v1 =[                                                              
    url(r'^api/v1/', 
        include('my_project.apps.agreements.api_v1.urls')),  
    url(r'^api/v1/',
    include('my_project.apps.authentication.api_v1.urls'))   ]

urlpatterns = [
    url(r'', include((api_v1,'v1'), namespace="v1")),
]

Если вместо этого в шаблоны URL я включаю вот так:

urlpatterns = [
    url(r'', include(api_v1, namespace="v1")),
]

У меня появляется следующая ошибка: 'Указание пространства имен в include ()без предоставления app_name 'django.core.exceptions.ImproperlyConfigured: указание пространства имен в include () без предоставления app_name не поддерживается.Установите атрибут app_name во включенном модуле или передайте 2-кортеж, содержащий список шаблонов и app_name вместо этого.

Дело в том, что v1 в качестве второго аргумента, "app_name", фактически егоне имя приложения, я просто поместил его там, чтобы не было ошибки ....

Также теперь, наоборот, я должен сделать это так (работает):

reverse('v1:authentication:authentication-user-detail', kwargs={'pk': '5'})
'/api/v1/users/5/'

И не так, как я хотел, это:

reverse('v1:authentication-user-detail' . .

ОБНОВЛЕНИЕ 3

Для последней проблемы я решил ее, комментируя app_name внутри файла url из конкретного приложения,Так было бы

# app_name = 'authentication'                                            
router = DefaultRouter()                                               
router.register(r'users', UserViewSet, base_name='authentication-user')
...