【问题标题】:Django rest framework custom Response middlewareDjango rest框架自定义Response中间件
【发布时间】:2019-05-01 13:53:22
【问题描述】:

我使用 Django Rest Framework 和 rest_auth(/login、/logout/、/register...) 我有一个中间件,通常由 user_logged_in 或 user_logged_out 信号触发。

在我的中间件中,我想使用来自 Rest 框架的 Response 对象。

我的中间件.py

from django.contrib.sessions.models import Session
from django.contrib.auth import logout
from django.contrib.auth.models import AnonymousUser
from rest_framework.response import Response
from rest_framework import status


class OneSessionPerUserMiddleware:
    def __init__(self, get_response):

        self.get_response = get_response

    def __call__(self, request):

        if request.user.is_authenticated:
            if request.user.session_key != Session.objects.filter(session_key__in = request.user.session_key):
                logout(request)
                return Response(request)
        return self.get_response(request)

我想我通过了我的条件,但我收到了这个错误:

 The response content must be rendered before it can be accessed

如何在中间件中正确使用 API Response 对象?
而且我真的不明白什么是:self.get_response = get_response?

【问题讨论】:

  • 只需删除您的return Response(request)。让您的视图使用return self.get_response(request) 处理请求。无论如何,您应该优雅地处理已注销的情况。
  • 所以我不能使用默认的API显示来添加一些自定义消息“已经登录”,例如?
  • 如果您真的想为中间件中的所有请求处理此问题,无论调用的 api 视图如何,请查看 Nafees 给出的答案。

标签: django django-rest-framework django-middleware


【解决方案1】:

return Response(request) 不是 django 可以处理的。 Ps 你将请求对象传递给Response 这是什么意思?

实际上来自rest框架的RequestResponse类与django不兼容。 rest 框架用APIView 中的Request 对象包装WSGIRequest(django 的内置),在从视图中获取Response 对象后,它通过解包创建HttpResponse 对象。所以Response 对象只能在rest framework 视图中使用。您可以像这样在中间件中使用django.http中的JsonResponse

from django.http import JsonResponse


if request.user.is_authenticated:
    if request.user.session_key != Session.objects.filter(session_key__in = request.user.session_key):
        logout(request)
        return JsonResponse({'logout': True}) # or whatever data you want to return 
return self.get_response(request)

【讨论】:

    【解决方案2】:

    首先:如果您使用 rest_framework.authentication.SessionAuthentication 以外的其他东西作为 authentication_class,那么 request.user 设置在中间件之外(在 View.dispatch 期间的某个地方)

    如果您确定 request.user 始终对应于 rest_framework 视图中的request.user 并且只想返回响应:

    A.看APIView.finalize_response:它相对“复杂”,因为它可以使用不同的渲染器(取决于accept-content请求头),它可能会改变头。如果你可以在中间件中访问你的视图实例,那么你可以调用view.finalize_response(request, response),如果你没有,那么你可以尝试做rest_framework.views.APIView().finalize_response(...)

    B.您可以使用django.http.HttpResponse:手动为正文生成字符串,并指定适当的content_typedjango.http.JsonResponse 也可能很方便。

    C.我假设你真的在做其他事情而不是return Response(request)(比如Response(data=...))。如果您只需要从视图返回结果,则删除return Response(request),以便return self.get_response(request) 启动。但是您正在注销,所以也许您应该返回django.http.HttpResponseRedirect 的一些实例

    【讨论】:

      猜你喜欢
      • 2016-05-03
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2021-05-30
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2021-01-30
      相关资源
      最近更新 更多