具有NameSpace API版本的Django DRF。修复为NoReverseMatch或配置不正确的错误

时间:2018-12-20 02:25:07

标签: django api django-rest-framework namespaces versioning

我想对我的api进行版本控制,但是无法使反向功能起作用。

我正在遵循DRF网站上提出的名称空间版本控制架构:namespaceversioning

我有一个名为 authentication 的应用,并且在我的身份验证文件夹中:

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

这是authentication / 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

例如,当我尝试从shell撤消时,出现以下错误:

> 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'

但是,如果我没有在应用程序URL中放置namespace ='v1',则这样:

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中有两个条目具有相同的命名空间 我会迟点检查。我认为解决方案是在我的主要网址中只有一个条目,然后将所有其余的都移到另一个文件中。

更新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")),
]

如果相反,我会在网址格式中添加如下内容:

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

我有以下错误: '在include()中指定名称空间而不提供app_name' django.core.exceptions.ImproperlyConfigured:不支持在include()中指定名称空间而不提供app_name。在随附的模块中设置app_name属性,或传递包含模式列表和app_name的2元组。

问题是,“ v1”是第二个参数,即“ app_name”,实际上它不是应用程序名称,我只是把它放在这里没有错误。...

现在,相反,我必须使它像这样(它可以工作):

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

不是我想要的那样:

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

更新3

对于最后一个问题,我通过在特定应用程序的url文件中注释app_name的方式解决了该问题。这样吧

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

0 个答案:

没有答案