Django остальные фреймворки Custom Response Middleware - PullRequest
1 голос
/ 01 мая 2019

Я использую Django Rest Framework с rest_auth (/ login, / logout /, / register ...) У меня есть Middleware, обычно запускаемый по сигналам user_logged_in или user_logged_out.

В своем Middleware я хочу использовать объект Response из среды Rest.

Мой 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 голосов
/ 01 мая 2019

Прежде всего: если вы используете в качестве аутентификационного класса что-то отличное от rest_framework.authentication.SessionAuthentication, тогда request.user устанавливается вне промежуточного программного обеспечения (где-то во время View.dispatch)

Если вы уверены, что запрос.Пользователь всегда соответствует request.user в представлениях rest_framework и просто хочет вернуть ответ:

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

0 голосов
/ 01 мая 2019

return Response(request) - это не то, с чем может справиться Джанго. Ps вы передаете объект запроса Response что это значит?

На самом деле Request и Response классы из структуры rest не совместимы с django. остальные рамки обертывают WSGIRequest (встроенный в django) с Request объектом в APIView и после получения 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)
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...