Python 路由器注册顺序影响输出

Python 路由器注册顺序影响输出,python,django,django-rest-framework,Python,Django,Django Rest Framework,我在尝试使用django rest框架实现Web服务时遇到了一个奇怪的问题。我有两个API——一个用于获取基于类别的新闻列表(作为URL参数提供),另一个用于获取新闻ID(作为URL参数提供)提供的新闻的详细信息。以下是我的应用程序的url.py代码: from django.urls import path from rest_framework import routers ... router = routers.DefaultRouter() router.register('news_

我在尝试使用django rest框架实现Web服务时遇到了一个奇怪的问题。我有两个API——一个用于获取基于类别的新闻列表(作为URL参数提供),另一个用于获取新闻ID(作为URL参数提供)提供的新闻的详细信息。以下是我的应用程序的
url.py
代码:

from django.urls import path
from rest_framework import routers
...
router = routers.DefaultRouter()
router.register('news_contents', NewsContentViewSet)
router.register('news_infos', NewsInfoViewSet)
router.register('categories', CategoryViewSet)
router.register(r'^articles/(?P<category_name>[-\w]+)', NewsItemViewSet, base_name="NewsInfo")
router.register(r'^articles/(?P<news_id>\d+)/details', NewsDetailViewSet, base_name="NewsInfo")

urlpatterns = router.urls
但是,当我更改这两个API的注册顺序时,这两个API开始按预期工作

工作
url.py

from django.urls import path
from rest_framework import routers
...
router = routers.DefaultRouter()
router.register('news_contents', NewsContentViewSet)
router.register('news_infos', NewsInfoViewSet)
router.register('categories', CategoryViewSet)
router.register(r'^articles/(?P<news_id>\d+)/details', NewsDetailViewSet, base_name="NewsInfo") #brought to above the listing API
router.register(r'^articles/(?P<category_name>[-\w]+)', NewsItemViewSet, base_name="NewsInfo")

urlpatterns = router.urls
从django.url导入路径
从rest_框架导入路由器
...
路由器=路由器。默认路由器()
router.register('news\u contents',NewsContentViewSet)
router.register('news\u infos',NewsInfoViewSet)
路由器寄存器('categories',CategoryViewSet)
router.register(r'^articles/(?P\d+)/details',NewsDetailViewSet,base_name=“NewsInfo”)#置于列表API之上
路由器.register(r'^articles/(?P[-\w]+)',NewsItemViewSet,base_name=“NewsInfo”)
urlpatterns=router.url
为什么会这样?我有一种感觉,当我添加更多的API时,无论这背后的原因是什么,都会让我陷入困境

调试时我注意到的另一件事是,我不希望有很多其他端点自动列为可用端点:

Using the URLconf defined in restnews.urls, Django tried these URL patterns, in this order:
rest/ ^news_contents/$ [name='newscontent-list']
rest/ ^news_contents\.(?P<format>[a-z0-9]+)/?$ [name='newscontent-list']
rest/ ^news_contents/(?P<pk>[^/.]+)/$ [name='newscontent-detail']
rest/ ^news_contents/(?P<pk>[^/.]+)\.(?P<format>[a-z0-9]+)/?$ [name='newscontent-detail']
rest/ ^news_infos/$ [name='newsinfo-list']
rest/ ^news_infos\.(?P<format>[a-z0-9]+)/?$ [name='newsinfo-list']
rest/ ^news_infos/(?P<pk>[^/.]+)/$ [name='newsinfo-detail']
rest/ ^news_infos/(?P<pk>[^/.]+)\.(?P<format>[a-z0-9]+)/?$ [name='newsinfo-detail']
rest/ ^^categories/$/$ [name='newsinfo-list']
rest/ ^^categories/$\.(?P<format>[a-z0-9]+)/?$ [name='newsinfo-list']
rest/ ^^categories/$/(?P<pk>[^/.]+)/$ [name='newsinfo-detail']
rest/ ^^categories/$/(?P<pk>[^/.]+)\.(?P<format>[a-z0-9]+)/?$ [name='newsinfo-detail']
rest/ ^^articles/(?P<news_id>\d+)/details/$ [name='NewsInfo-list']
rest/ ^^articles/(?P<news_id>\d+)/details\.(?P<format>[a-z0-9]+)/?$ [name='NewsInfo-list']
rest/ ^^articles/(?P<news_id>\d+)/details/(?P<pk>[^/.]+)/$ [name='NewsInfo-detail']
rest/ ^^articles/(?P<news_id>\d+)/details/(?P<pk>[^/.]+)\.(?P<format>[a-z0-9]+)/?$ [name='NewsInfo-detail']
rest/ ^^articles/(?P<category_name>[-\w]+)/$ [name='NewsInfo-list']
rest/ ^^articles/(?P<category_name>[-\w]+)\.(?P<format>[a-z0-9]+)/?$ [name='NewsInfo-list']
rest/ ^^articles/(?P<category_name>[-\w]+)/(?P<pk>[^/.]+)/$ [name='NewsInfo-detail']
rest/ ^^articles/(?P<category_name>[-\w]+)/(?P<pk>[^/.]+)\.(?P<format>[a-z0-9]+)/?$ [name='NewsInfo-detail']
rest/ ^$ [name='api-root']
rest/ ^\.(?P<format>[a-z0-9]+)/?$ [name='api-root']
Django使用restnews.URL中定义的URLconf,按以下顺序尝试了这些URL模式:
rest/^news\u contents/$[name='newcontent-list']
rest/^news\u contents\(?P[a-z0-9]+)/?$[name='newcontent-list']
rest/^news\u contents/(?P[^/]+)/$[name='newcontent-detail']
rest/^news\u contents/(?P[^/]+)\(?P[a-z0-9]+)/?$[name='newscant-detail']
rest/^news\u infos/$[name='newsinfo-list']
rest/^news\u infos\(?P[a-z0-9]+)/?$[name='newsinfo-list']
rest/^news\u infos/(?P[^/]+)/$[name='newsinfo-detail']
rest/^news\u infos/(?P[^/]+)\(?P[a-z0-9]+)/?$[name='newsinfo-detail']
rest/^^ categories/$/$[name='newsinfo-list']
rest/^^^ categories/$\。(?P[a-z0-9]+)/?$[name='newsinfo-list']
rest/^^^ categories/$/(?P[^/]+)/$[name='newsinfo-detail']
rest/^^^类别/$/(?P[^/]+)\(?P[a-z0-9]+)/?$[name='newsinfo-detail']
rest/^^^ articles/(?P\d+)/details/$[name='NewsInfo-list']
其余/^^^文章/(?P\d+)/细节\.(?P[a-z0-9]+)/?$[name='NewsInfo-list']
rest/^^^ articles/(?P\d+)/details/(?P[^/]+)/$[name='NewsInfo-detail']
rest/^^^ articles/(?P\d+)/details/(?P[^/]+)\(?P[a-z0-9]+)/?$[name='NewsInfo-detail']
rest/^^articles/(?P[-\w]+)/$[name='NewsInfo-list']
其余/^^^文章/(?P[-\w]+)\(?P[a-z0-9]+)/?$[name='NewsInfo-list']
rest/^^ articles/(?P[-\w]+)/(?P[^/]+)/$[name='NewsInfo-detail']
其余/^^^文章/(?P[-\w]+)/(?P[^/]+)\(?P[a-z0-9]+)/?$[name='NewsInfo-detail']
rest/^$[name='api-root']
rest/^\(?P[a-z0-9]+)/?$[name='api-root']

我只提供了5个端点,其余的端点都不需要,因此需要删除。这些问题是否有某种联系?如何解决这些问题?

这就是ModelViewset和DefaultRouter类组合的行为方式。从中,它默认提供了一系列端点 如果你正在做,这是非常方便的。

从您的描述中,我了解到您不是在处理
CRUD
操作,因此您不能使用
DefaultRouter
ModelViewset


因此,我建议使用
rest\u framework.views.APIView
类。

示例

views.py
在你的
url.py中

from django.conf.urls import url

urlpatterns = [
    url(r'mysample/', MyViewClass.as_view())

]

参考资料
1.
2.
3.

更新-1
读《Django》

Django如何处理请求

当用户从您的 Django供电站点,这是系统遵循的算法 确定要执行的Python代码:

  • Django确定要使用的根URLconf模块。通常,这是ROOT_URLCONF设置的值,但是如果 HttpRequest对象有一个名为urlconf的属性(由中间件设置) 请求处理),其值将代替 ROOT\u URLCONF设置
  • Django加载该Python模块并查找变量urlpatterns。这应该是一个Python列表,格式为 函数django.conf.urls.patterns()
  • Django按顺序运行每个URL模式,并在与请求的URL匹配的第一个模式处停止。
  • 一旦其中一个正则表达式匹配,Django就会导入并调用给定的视图,该视图是一个简单的Python函数。视图通过了一个 HttpRequest作为其第一个参数,以及在正则表达式中捕获的任何值 作为剩余的论点
  • 如果没有匹配的正则表达式,或者在此过程中的任何时候引发异常,Django将调用适当的错误处理视图。 请参阅下面的错误处理

  • 目前我使用的是ModelViewSet,我需要更改它?好的,如果您使用的是
    路由器
    ,则无法删除这些自动生成的URL,如果您不使用路由器,则必须手动放置所有URL模式,你的api提供了什么样的CRUD功能?我昨天刚开始学习Django,对CRUD和all等所有选项都不太熟悉。即使其他URL是由路由器自动生成的,订单问题背后的原因是什么?当然,首先让我看看CRUD是什么。我是前端的家伙,只是把我的头放在支持的技术上。所有这些术语都是全新的。
    from rest_framework.views import APIView
    from rest_framework.response import Response
    
    
    class MyViewClass(APIView):
        def get(self, *args, **kwargs):  # This fucntion will handle your "HTTP GET" requests
            # put your logic here
            return Response(data={"mymsg": "this is my response"})
    
        def post(self, *args, **kwargs):
            return Response("This is post method")
    from django.conf.urls import url
    
    urlpatterns = [
        url(r'mysample/', MyViewClass.as_view())
    
    ]