mirror of
https://github.com/encode/django-rest-framework.git
synced 2025-08-02 03:20:12 +03:00
Reduce the number of circular references
This should avoid high memory usage due to largish object not being deleted immediately by the reference counter. Signed-off-by: Pierre Fersing <pierre.fersing@bleemeo.com>
This commit is contained in:
parent
ff4429fad4
commit
e884a0a964
|
@ -13,6 +13,29 @@ from django.utils.six.moves.http_client import responses
|
||||||
from rest_framework.serializers import Serializer
|
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):
|
class Response(SimpleTemplateResponse):
|
||||||
"""
|
"""
|
||||||
An HttpResponse that allows its data to be rendered into
|
An HttpResponse that allows its data to be rendered into
|
||||||
|
@ -48,6 +71,8 @@ class Response(SimpleTemplateResponse):
|
||||||
for name, value in six.iteritems(headers):
|
for name, value in six.iteritems(headers):
|
||||||
self[name] = value
|
self[name] = value
|
||||||
|
|
||||||
|
self.add_post_render_callback(cleanup)
|
||||||
|
|
||||||
@property
|
@property
|
||||||
def rendered_content(self):
|
def rendered_content(self):
|
||||||
renderer = getattr(self, 'accepted_renderer', None)
|
renderer = getattr(self, 'accepted_renderer', None)
|
||||||
|
|
|
@ -100,7 +100,16 @@ class ViewSetMixin(object):
|
||||||
self.kwargs = kwargs
|
self.kwargs = kwargs
|
||||||
|
|
||||||
# And continue as usual
|
# 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
|
# take name and docstring from class
|
||||||
update_wrapper(view, cls, updated=())
|
update_wrapper(view, cls, updated=())
|
||||||
|
|
|
@ -167,7 +167,7 @@ class TestRootView(TestCase):
|
||||||
request = factory.post('/', data, HTTP_ACCEPT='text/html')
|
request = factory.post('/', data, HTTP_ACCEPT='text/html')
|
||||||
response = self.view(request).render()
|
response = self.view(request).render()
|
||||||
expected_error = '<span class="help-block">Ensure this field has no more than 100 characters.</span>'
|
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
|
EXPECTED_QUERIES_FOR_PUT = 2
|
||||||
|
@ -314,7 +314,7 @@ class TestInstanceView(TestCase):
|
||||||
request = factory.put('/', data, HTTP_ACCEPT='text/html')
|
request = factory.put('/', data, HTTP_ACCEPT='text/html')
|
||||||
response = self.view(request, pk=1).render()
|
response = self.view(request, pk=1).render()
|
||||||
expected_error = '<span class="help-block">Ensure this field has no more than 100 characters.</span>'
|
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):
|
class TestFKInstanceView(TestCase):
|
||||||
|
|
Loading…
Reference in New Issue
Block a user