diff --git a/rest_framework/request.py b/rest_framework/request.py index 93109226d..1b1a0a649 100644 --- a/rest_framework/request.py +++ b/rest_framework/request.py @@ -8,6 +8,7 @@ The wrapped request then offers a richer API, in particular : - full support of PUT method, including support for file uploads - form overloading of HTTP method, content type and content """ +import contextvars import io import sys from contextlib import contextmanager @@ -149,6 +150,8 @@ class Request: authenticating the request's user. """ + _context_instance = contextvars.ContextVar('request') + def __init__(self, request, parsers=None, authenticators=None, negotiator=None, parser_context=None): assert isinstance(request, HttpRequest), ( @@ -458,3 +461,11 @@ class Request: # Hack to allow our exception handler to force choice of # plaintext or html error responses. self._request.is_ajax = lambda: value + + @classmethod + def get_current(cls, default=None): + return cls._context_instance.get(default) + + @classmethod + def set_current(cls, value): + return cls._context_instance.set(value) diff --git a/rest_framework/serializers.py b/rest_framework/serializers.py index e27f8a47c..815e97e29 100644 --- a/rest_framework/serializers.py +++ b/rest_framework/serializers.py @@ -29,6 +29,7 @@ from django.utils.translation import gettext_lazy as _ from rest_framework.compat import postgres_fields from rest_framework.exceptions import ErrorDetail, ValidationError from rest_framework.fields import get_error_detail, set_value +from rest_framework.request import Request from rest_framework.settings import api_settings from rest_framework.utils import html, model_meta, representation from rest_framework.utils.field_mapping import ( @@ -115,6 +116,12 @@ class BaseSerializer(Field): self.partial = kwargs.pop('partial', False) self._context = kwargs.pop('context', {}) kwargs.pop('many', None) + + if isinstance(self._context, dict) and ('request' not in self._context): + request = Request.get_current() + if request: + self._context['request'] = request + super().__init__(**kwargs) def __new__(cls, *args, **kwargs): diff --git a/rest_framework/views.py b/rest_framework/views.py index 4c30029fd..2bc4fe32f 100644 --- a/rest_framework/views.py +++ b/rest_framework/views.py @@ -489,9 +489,11 @@ class APIView(View): """ self.args = args self.kwargs = kwargs + self.headers = self.default_response_headers # deprecate? + request = self.initialize_request(request, *args, **kwargs) self.request = request - self.headers = self.default_response_headers # deprecate? + Request.set_current(request) try: self.initial(request, *args, **kwargs)