【问题标题】:Django-rest-framework: set default renderer not working?Django-rest-framework:设置默认渲染器不起作用?
【发布时间】:2015-04-04 22:17:45
【问题描述】:

我正在尝试构建一个默认输出 JSON 的 Django-rest-framework REST API,但也有可用的 XML。

我已阅读Renderers chapter of the documentation section on default ordering,并将其放入我的设置文件中:

REST_FRAMEWORK = {
    'DEFAULT_RENDERER_CLASSES': (
        'rest_framework.renderers.JSONRenderer',
        'rest_framework_xml.renderers.XMLRenderer',
    )
}

但是,默认情况下这会输出 XML。切换顺序没有区别。

如果我将 format=json 附加到 URL,并且完全删除 XMLRenderer 行,我会得到 JSON。

如何将 JSON 设置为默认值?

我正在使用 Django 的 v1.7 和 Django-rest-framework 的 v3.1.1。

更新:这里要求的是我的观点的代码:

class CountyViewSet(viewsets.ModelViewSet):
    queryset = County.objects.all()
    serializer_class = CountySerializer

还有序列化器:

from rest_framework import serializers
class CountySerializer(serializers.ModelSerializer):
    class Meta:
        model = County
        fields = ('id', 'name', 'name_slug', 'ordering')

最后来自我的 urls 文件:

router = routers.DefaultRouter()
router.register(r'county', CountyViewSet)
urlpatterns = [
    url(r'^', include(router.urls)),
]

【问题讨论】:

  • 这个问题有什么解决办法吗?我也面临同样的问题。

标签: python django django-rest-framework


【解决方案1】:

我的解决方案:文件 renderers.py

from rest_framework.negotiation import DefaultContentNegotiation

class IgnoreClientContentNegotiation(DefaultContentNegotiation):

    logger = logging.getLogger(__name__)
    def select_renderer(self, request, renderers, format_suffix):
        """
        Select the first renderer in the `.renderer_classes` list.
        """
        # Allow URL style format override.  eg. "?format=json
        format_query_param = self.settings.URL_FORMAT_OVERRIDE
        format = format_suffix or request.query_params.get(format_query_param)
        request.query_params.get(format_query_param), format))

        if format is None:
            return (renderers[0], renderers[0].media_type)
        else:
            return DefaultContentNegotiation.select_renderer(self, request, renderers, format_suffix)

现在只需要在settings.py中添加

REST_FRAMEWORK = { 
 (...)
'DEFAULT_CONTENT_NEGOTIATION_CLASS': 'myapp.renderers.IgnoreClientContentNegotiation',
}

【讨论】:

    【解决方案2】:

    您能否发布实际视图的代码?

    您是否在视图中定义了renderer_classes?因为这会覆盖默认设置。

    class YourView(APIView):
        renderer_classes = (XMLRenderer, JSONRenderer, )
    

    【讨论】:

    • 谢谢。我已经更新了这个问题。不,我没有在我的视图中定义renderer_classes
    • 如果我尝试在单个视图上设置renderer_classes,那么无论我将类放入哪个顺序,XML 仍然是默认设置。也许这是因为 XML 渲染器实际上是一个第三方模块 (djangorestframework_xml) 不想与默认值很好地配合?
    【解决方案3】:

    您遇到的最有可能的问题是,尤其是在使用浏览器进行测试时,XML 在 Accepts 标头中位于 JSON 之前。正因为如此,Django REST 框架正在呈现 XML,因为您特别请求它,即使它不是您所期望的。

    通过为 DRF 提供默认渲染器列表,您是在告诉它“如果我不告诉您在我的视图中使用其他渲染器,请使用这些渲染器”。然后,DRF 会将这些媒体类型与 Accepts 标头中的媒体类型进行比较,以确定在响应中使用的最佳渲染器。顺序无关紧要,除非您没有在 Accepts 标头中包含特定的媒体类型,此时它应该默认为列表中的第一个。

    【讨论】:

    • 谢谢。问题是我不能强迫我的用户(可能正在使用任何浏览器)以某种方式设置他们的Accepts 标头。那么是不是基本不可能默认返回JSON,但也服务XML,使用DRF?
    • application/xmlAccepts 标头中时,默认情况下不可能强制DRF不返回 XML,没有 强制 XML 在不同的媒体类型下返回。这将对任何实际需要使用您的 API 的 XML 客户端产生不利影响,这不是一个好主意。
    • 如果 DRF 遵守我的设置中指定的顺序,而不是客户端的 Accepts 标头中指定的顺序,那就更好了。如果需要,客户端始终可以使用format=xml 专门请求 XML。
    • 仔细看看github.com/encode/django-rest-framework/blob/master/… 看来我,rest_framework 优先于浏览器请求 ACCEPT_HEADER 而不是 render_classes 中的顺序。
    【解决方案4】:

    塞尔吉奥的回答是正确的。

    只是为将来遇到此问题的任何人添加更多详细信息。

    1. 将 djangorestframework-xml 添加到 pipfile

    2. 更新

    RENDERER_CLASSES = (
        'rest_framework.renderers.JSONRenderer',
        'rest_framework_xml.renderers.XMLRenderer',
    )
    
    REST_FRAMEWORK = {
       ...
        'DEFAULT_RENDERER_CLASSES': RENDERER_CLASSES,
    }
    
    1. 将 rest_framework_xml 添加到 INSTALLED_APPS
    INSTALLED_APPS = [
        ...
        'rest_framework',
        'rest_framework_xml',
    ]
    
    1. 遵循 Sérgio 关于创建“renderers.py”的建议

    【讨论】:

      猜你喜欢
      • 2019-09-15
      • 2013-06-24
      • 2016-04-14
      • 1970-01-01
      • 2019-01-25
      • 2015-10-05
      • 2019-04-12
      • 1970-01-01
      • 2021-11-19
      相关资源
      最近更新 更多