在DefaultRouter的根api视图上订购项目

时间:2014-06-19 16:37:39

标签: django django-rest-framework

我正在使用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项而不修改源代码?

3 个答案:

答案 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])