【问题标题】:Django REST returns 404 when URL param is changed更改 URL 参数时,Django REST 返回 404
【发布时间】:2018-03-01 15:46:14
【问题描述】:

我正在使用 Django REST 框架来创建一个支持 JSON 和 CSV 输出的 API。

我的urls.py 中有这一行:

url(r'^api/events/$', views.EventsView.as_view(), name='events'),

EventsView 看起来像这样:

class EventsView(APIView):

    def dispatch(self, request, *args, **kwargs):
        return super(EventsView, self).dispatch(request, *args, **kwargs)

    def get(self, request):

        logger.info("Here")

        events = EventsQuery(request)
        if events.is_valid():
            events.build_response()

        return events.get_response()

如果我访问 /api/events/?format=json,我会得到一组有效的 JSON 结果,我会看到“这里”记录到我的日志文件中

如果我访问/api/events/?format=csv,我会收到一个带有 JSON 正文的 404 响应

{
"detail": "Not found."
}

...并且没有任何记录

缺乏日志记录让我很头疼。就好像它甚至没有进入 EventsView 类,但是更改 URL 中的查询字符串值如何阻止它被路由到该类?以及如何找出它被路由到的位置?


编辑:EventsQuery.get_response() 的内容是:

def get_response(self):
    if self.has_error:
        self.response = {
            'success': self.success,
            'errors': self.errors
        }
        resp_status = status.HTTP_400_BAD_REQUEST
    else:
        resp_status = status.HTTP_200_OK

    return Response(
        self.response, status=resp_status, content_type=self.content_type
    )

【问题讨论】:

  • 您是否注意到控制台中的错误?
  • 除了 404 记录之外,没有。
  • EventsQuery 是什么,get_response() 返回什么?一个 sn-p 会很好
  • 点击here查看类似问题和有效答案
  • 您为支持 CSV 做了哪些工作?您使用的是特定库吗?

标签: python json django rest csv


【解决方案1】:

我刚刚遇到这个问题并深入了解它。

根本原因是,在 DRF 中,'format' url 参数用于确定在内容协商阶段使用哪个渲染器类,如果没有一个渲染器类具有匹配的格式属性,则内容协商器返回 404格式 url 查询参数。看看rest_framework.negotiation.DefaultContentNegotiation.filter_renderersmethod中的代码。

其他人在 DRF 数据表存储库中遇到了这个问题 - https://github.com/izimobil/django-rest-framework-datatables/issues/4

为了后人重复我在那里发布的内容 - 您可以(至少)通过两种方式解决这个问题。最可靠的方法是创建您自己的内容协商类,该类在过滤渲染器时遵循不同的登录。出于我的目的,我只想使用format kwarg 来确定要在视图集中使用哪个序列化程序类,我很高兴通过创建一个具有我想要使用的格式属性的虚拟渲染器类来解决这个问题。这是一个例子:

from rest_framework.renderers import JSONRenderer

class GeoJsonRenderer(JSONRenderer):
    format = "geojson"

class MyViewSet(ModelPermissionsMixin, ModelViewSet):
    def get_renderers(self):
        return super().get_renderers() + [GeoJsonRenderer()]

    def get_serializer_class(self):
        format = self.request.query_params.get("format")
        if format and format == "geojson":
            return GeoJsonSerialiser
        return super().get_serializer_class()

【讨论】:

    【解决方案2】:

    我仍然不清楚根本原因,但我通过使用 format_suffix_patterns 传递格式参数而不是将其作为查询字符串参数传递来解决该问题。我确实通过重写 APIView.handle_exception() 确认了父类引发了 404 异常,但我不知道为什么。

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 2013-01-06
      • 2017-07-01
      • 2019-10-29
      • 2020-08-26
      • 2019-02-04
      • 2022-09-28
      • 2017-03-04
      相关资源
      最近更新 更多