我正在使用DRF提供的DefaultRouter,因为我需要root api视图。但是,该视图上的项目不是任何逻辑顺序。我查看了源代码,发现每个条目都被放入一个字典中(这本身就没有订购)。
class DefaultRouter(SimpleRouter):
"""
The default router extends the SimpleRouter, but also adds in a default
API root view, and adds format suffix patterns to the URLs.
"""
include_root_view = True
include_format_suffixes = True
root_view_name = 'api-root'
def get_api_root_view(self):
"""
Return a view to use as the API root.
"""
api_root_dict = {}
list_name = self.routes[0].name
for prefix, viewset, basename in self.registry:
api_root_dict[prefix] = list_name.format(basename=basename)
class APIRoot(views.APIView):
_ignore_model_permissions = True
def get(self, request, format=None):
ret = {}
for key, url_name in api_root_dict.items():
ret[key] = reverse(url_name, request=request, format=format)
return Response(ret)
return APIRoot.as_view()
我想按字母顺序在root api视图上订购项目,并且可以通过修改源来轻松完成。但我想知道,有没有人想出解决方案来订购根api项而不修改源代码?
答案 0 :(得分:3)
根据您的建议以及Denis Cornehi的答案中的第一点,这里是DefaultRouter的扩展,它按照其base_names对URL进行排序:
# myapp/routers.py
from rest_framework import routers
from rest_framework import views
from rest_framework.response import Response
from rest_framework.reverse import reverse
import operator
import collections
class OrderedDefaultRouter(routers.DefaultRouter):
def get_api_root_view(self):
"""
Return a view to use as the API root but do it with ordered links.
"""
api_root_dict = {}
list_name = self.routes[0].name
for prefix, viewset, basename in self.registry:
api_root_dict[prefix] = list_name.format(basename=basename)
class APIRoot(views.APIView):
_ignore_model_permissions = True
def get(self, request, format=None):
ret = {}
for key, url_name in api_root_dict.items():
ret[key] = reverse(url_name, request=request, format=format)
sorted_ret = collections.OrderedDict(sorted(ret.items(), key=operator.itemgetter(0)))
return Response(sorted_ret)
return APIRoot.as_view()
答案 1 :(得分:0)
我在这里看到两种方式:
如您所建议,覆盖路由器,更改APIRoot视图(返回OrderedDict
应该足够了)。在这种情况下,我会增加DRF的问题(或许)为每个人改变它。
扩展/覆盖JSONRenderer以允许在转储JSON时对键进行排序。然后扩展BrowsableAPIRenderer以设置此属性。或者只是排序所有回复。 (并且,对于DRF的每个用户而言,这也许是有趣的)。
答案 2 :(得分:0)
使用DRF 3.11.2 [不确定以下版本将从哪个旧版本开始工作],您也可以这样做
router = DefaultRouter()
# Register routes ...
router.registry.sort(key=lambda x: x[0])