web-dev-qa-db-fra.com

Comment renvoyer un objet rest_framework.response à partir d'une classe de middleware personnalisé Django?

J'essaie d'écrire une classe de middleware qui garantit que l'utilisateur est connecté. Mais le problème est que cette classe de middleware ne sera applicable qu'à un petit ensemble de vues et ces vues renvoient l'objet Response d'un DRF plutôt que le HTTPResponse objet et ces vues sont également décorées à l'aide de api_view.

Ainsi, lorsque j'essaie de renvoyer un objet Response de la classe middleware, il déclenche cette erreur.

 assert renderer, ".accepted_renderer not set on Response"
AssertionError: .accepted_renderer not set on Response

J'ai cherché un peu sur SO et je suppose que l'erreur est en quelque sorte liée à api_view décorateur. Mais je ne sais pas comment résoudre ce problème.

Toute aide est appréciée. :)

28
Adil Malik

J'ai récemment rencontré ce problème. Cette solution n'utilise pas la réponse Django Rest Framework), mais si votre serveur renvoie simplement JSON, cette solution peut fonctionner pour vous.

Nouveau dans Django 1.7 est le type de réponse JSONResponse.

https://docs.djangoproject.com/en/1.7/ref/request-response/#jsonresponse-objects

Dans le middleware, vous pouvez renvoyer ces réponses sans avoir toutes les erreurs "Aucun rendu accepté" et "La réponse n'a aucun encodage d'attribut".

C'est un format très similaire à la réponse DRF

L'importation est la suivante: from Django.http import JsonResponse

Et comment vous l'utilisez:

return JsonResponse({'error': 'Some error'}, status=401)

J'espère que cela vous aidera!

23
Jordan

J'ai résolu ce problème moi-même en imitant la façon dont les vues rest frameworks corrigent l'objet de réponse avec accepted_renderer, accepted_media_type Et renderer_context. Dans mon cas, je voulais juste retourner une réponse 401 en utilisant la classe rest frameworks Response, en partie parce que mes tests s'attendent à une réponse de framework rest lorsque j'appelle self.client.get(...) et affirme response.data.

Dans d'autres cas d'utilisation, vous devrez peut-être fournir des informations supplémentaires dans le renderer_context Ou utiliser un autre accepted_renderer.

from rest_framework import status
from rest_framework.renderers import JSONRenderer
from rest_framework.response import Response

class MiddlewareClass(object):

    def __init__(self, get_response):
        self.get_response = get_response

    def unauthorized_response(self, request):
        response = Response(
            {"detail": "This action is not authorized"},
            content_type="application/json",
            status=status.HTTP_401_UNAUTHORIZED,
        )
        response.accepted_renderer = JSONRenderer()
        response.accepted_media_type = "application/json"
        response.renderer_context = {}

        return response

    def __call__(self, request: HttpRequest):
        if not self.authorized(request):
            return self.unauthorized_response(request)
        return self.get_response(request)
8
A. J. Parr