Django rest 框架自定义 Response 中间件
Django rest framework custom Response 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响应对象?
而且我真的不明白什么是: self.get_response = get_response ?
return Response(request)
不是 django 可以处理的。 Ps 您正在将请求对象传递给 Response
这是什么意思?
实际上,来自 rest 框架的 Request
和 Response
类 与 django 不兼容。 rest framework 在 APIView
中用 Request
对象包装 WSGIRequest
(django 的内置函数),在从视图中获取 Response
对象后,它通过解包创建 HttpResponse
对象。所以 Response
对象只能在 rest 框架视图中使用。您可以在这样的中间件中使用 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)
首先:如果您使用 rest_framework.authentication.SessionAuthentication
以外的东西作为 authentication_class,那么 request.user
是在中间件之外设置的(在 View.dispatch
期间的某处)
如果您确定 request.user 始终对应 rest_framework 视图中的 request.user
,并且只想 return 回复:
一个。看APIView.finalize_response
:相对"complex"因为它可以使用不同的渲染器(取决于accept-content请求头),它可能会改变头。如果你可以在中间件中访问你的视图实例,那么你可以调用 view.finalize_response(request, response)
,如果你没有它,那么你可以尝试做 rest_framework.views.APIView().finalize_response(...)
乙。您可以使用django.http.HttpResponse
:手动生成正文字符串,并指定适当的content_type
。 django.http.JsonResponse
也可能很方便。
C.我假设您实际上不是在 return Response(request)
而是在做其他事情(例如 Response(data=...)
)。如果您只需要 return 查看结果,则删除 return Response(request)
,以便 return self.get_response(request)
开始。但是您正在注销,所以也许您应该 return 一些实例共 django.http.HttpResponseRedirect
我将 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响应对象?
而且我真的不明白什么是: self.get_response = get_response ?
return Response(request)
不是 django 可以处理的。 Ps 您正在将请求对象传递给 Response
这是什么意思?
实际上,来自 rest 框架的 Request
和 Response
类 与 django 不兼容。 rest framework 在 APIView
中用 Request
对象包装 WSGIRequest
(django 的内置函数),在从视图中获取 Response
对象后,它通过解包创建 HttpResponse
对象。所以 Response
对象只能在 rest 框架视图中使用。您可以在这样的中间件中使用 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)
首先:如果您使用 rest_framework.authentication.SessionAuthentication
以外的东西作为 authentication_class,那么 request.user
是在中间件之外设置的(在 View.dispatch
期间的某处)
如果您确定 request.user 始终对应 rest_framework 视图中的 request.user
,并且只想 return 回复:
一个。看APIView.finalize_response
:相对"complex"因为它可以使用不同的渲染器(取决于accept-content请求头),它可能会改变头。如果你可以在中间件中访问你的视图实例,那么你可以调用 view.finalize_response(request, response)
,如果你没有它,那么你可以尝试做 rest_framework.views.APIView().finalize_response(...)
乙。您可以使用django.http.HttpResponse
:手动生成正文字符串,并指定适当的content_type
。 django.http.JsonResponse
也可能很方便。
C.我假设您实际上不是在 return Response(request)
而是在做其他事情(例如 Response(data=...)
)。如果您只需要 return 查看结果,则删除 return Response(request)
,以便 return self.get_response(request)
开始。但是您正在注销,所以也许您应该 return 一些实例共 django.http.HttpResponseRedirect