Django rest框架自定义Response中间件

时间:2019-05-01 13:53:22

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

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

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

我的middleware.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?

2 个答案:

答案 0 :(得分:0)

return Response(request)不是django可以处理的。 ps您正在将请求对象传递给Response是什么意思?

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

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)

答案 1 :(得分:0)

首先:如果您使用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_type。而且django.http.JsonResponse也可能很方便。

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