contextvars for request context

This commit is contained in:
dalerzafarovich 2023-03-21 23:35:58 +05:00
parent c9e7b68a4c
commit 06d21eb246
3 changed files with 21 additions and 1 deletions

View File

@ -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)

View File

@ -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):

View File

@ -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)