【问题标题】:django rest framework dynamic "manual" @detail_route declarationsdjango rest 框架动态“手动”@detail_route 声明
【发布时间】:2018-05-10 14:06:58
【问题描述】:

我的 REST 声明中有一些高度重复的代码,因此我决定注入 @detail_route 方法,而不是一遍又一遍地重新声明它们。

但是,在 drf 3.7.7 版和 3.8.2 版之间,有些东西(嗯,URL 生成函数,就是这样)发生了变化,这些动态添加的详细路由不再在路由器中注册/呈现为 URL。

我的代码:

class SiteTreeViewSet(viewsets.ReadOnlyModelViewSet):
.....

def generic_model_rest(model_, field, serfield):

    @detail_route()
    def _f(self, request, pk=None):
        itm = SiteTree.objects.get(pk=int(pk))
        serializer = globals()['Settings' + serfield + 'Serializer']
        if serfield in ('WWW', 'Oth',):
            data = serializer(getattr(itm, 'get_sett_' + serfield.lower())(), many=True)
        else:
            data = serializer(getattr(itm, 'get_sett_' + serfield.lower())())
        return Response(data.data)

setattr(SiteTreeViewSet, 'settings_%s' % serfield.lower(), _f)



generic_model_rest(SettingsApartment, 'apartment', 'Apt')
generic_model_rest(SettingsSwitch, 'switch', 'Swt')
generic_model_rest(SettingsWeblinks, 'weblinks', 'WWW')
generic_model_rest(SettingsWeblinks, 'weblinks1', 'WW1')
generic_model_rest(SettingsOther, 'other', 'Oth')

router.register(r'rest/sitetree', SiteTreeViewSet, 'SiteTree')

我还有其他“手动”插入详细路线的选项吗?

【问题讨论】:

    标签: django django-rest-framework python-3.6


    【解决方案1】:

    较新版本的 DRF 没有 detail_route 和 list_route 装饰器 你可以试试关注

    from rest_framework.decorators import action
    ...
    ...
    ...
    
    
    @action(detail=True)
    def _f(self, request, pk=None):
        ......
    

    在这里签到http://www.django-rest-framework.org/api-guide/viewsets/

    【讨论】:

      【解决方案2】:

      @detail_route 和 @list_route 现在已弃用,取而代之的是行动路线。建议降级或使用@action 路由。

      详见补丁 3.8.0 http://www.django-rest-framework.org/topics/release-notes/

      【讨论】:

      • 已弃用它们,但我只是将所有内容更改为@action,结果相同:它只是不起作用。
      【解决方案3】:

      彻底调试:新版本中的 URL 组合已完全修改(阅读:更改)。现在 url 将直接由函数名组成,而不是由插入到目标 ViewSet 类中的函数组成。

      最终,我不得不改变以下两点:

      @action(detail=True, url_path='settings_%s' % serfield.lower())
      def _f(self, request, pk=None):
          .....
      
      _f.__name__ = 'settings_%s' % serfield.lower()
      

      我认为没有必要更改 @action,但我懒得检查。

      我必须将url_path 参数添加到装饰器本身,然后还设置函数的__name__ 属性。后者是必要的,因为 drf 在构建路由时将其用于内部字典的唯一性。前者现在在装饰期间自动生成,而不是像以前那样在评估/路由期间自动生成。

      【讨论】:

        猜你喜欢
        • 1970-01-01
        • 2016-02-27
        • 2016-02-15
        • 2020-01-27
        • 2017-12-16
        • 1970-01-01
        • 1970-01-01
        • 2012-12-08
        • 2017-04-26
        相关资源
        最近更新 更多