This commit is contained in:
Pierre Fersing 2018-08-03 08:13:42 +00:00 committed by GitHub
commit 64f67bca3d
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
3 changed files with 37 additions and 3 deletions

View File

@ -13,6 +13,29 @@ from django.utils.six.moves.http_client import responses
from rest_framework.serializers import Serializer
def cleanup(response):
""" Cleanup circular reference between view/request/response object
This reduce load on GC and help to keep low memory usage even
if some response are larger.
"""
view = response.renderer_context.get('view')
request = response.renderer_context.get('request')
if view:
view.response = None
view.request = None
if request:
request.parser_context.clear()
response.renderer_context.clear()
# Re-add request in renderer_context. It does not seem to cause
# circular reference and is needed for tests.
response.renderer_context['request'] = request
class Response(SimpleTemplateResponse):
"""
An HttpResponse that allows its data to be rendered into
@ -48,6 +71,8 @@ class Response(SimpleTemplateResponse):
for name, value in six.iteritems(headers):
self[name] = value
self.add_post_render_callback(cleanup)
@property
def rendered_content(self):
renderer = getattr(self, 'accepted_renderer', None)

View File

@ -113,7 +113,16 @@ class ViewSetMixin(object):
self.kwargs = kwargs
# And continue as usual
return self.dispatch(request, *args, **kwargs)
result = self.dispatch(request, *args, **kwargs)
# break our circular reference before finishing
for method in actions:
delattr(self, method)
if hasattr(self, 'head'):
delattr(self, 'head')
return result
# take name and docstring from class
update_wrapper(view, cls, updated=())

View File

@ -167,7 +167,7 @@ class TestRootView(TestCase):
request = factory.post('/', data, HTTP_ACCEPT='text/html')
response = self.view(request).render()
expected_error = '<span class="help-block">Ensure this field has no more than 100 characters.</span>'
assert expected_error in response.rendered_content.decode('utf-8')
assert expected_error in response.content.decode('utf-8')
EXPECTED_QUERIES_FOR_PUT = 2
@ -314,7 +314,7 @@ class TestInstanceView(TestCase):
request = factory.put('/', data, HTTP_ACCEPT='text/html')
response = self.view(request, pk=1).render()
expected_error = '<span class="help-block">Ensure this field has no more than 100 characters.</span>'
assert expected_error in response.rendered_content.decode('utf-8')
assert expected_error in response.content.decode('utf-8')
class TestFKInstanceView(TestCase):