summaryrefslogtreecommitdiff
path: root/django/http
diff options
context:
space:
mode:
authorAymeric Augustin <aymeric.augustin@m4x.org>2012-10-23 22:25:38 +0200
committerAymeric Augustin <aymeric.augustin@m4x.org>2012-10-24 17:08:37 +0200
commit495a8b8107dbd4fb511954bcd2322d125addd94e (patch)
tree3d1c7864ec421dc046085d1f8c085335c3c514b3 /django/http
parent83041ca8025425530fcd32b50f247077ac0a5b74 (diff)
Fixed #6527 -- Provided repeatable content access
in HttpResponses instantiated with iterators.
Diffstat (limited to 'django/http')
-rw-r--r--django/http/response.py30
1 files changed, 25 insertions, 5 deletions
diff --git a/django/http/response.py b/django/http/response.py
index 4a5c479419..e9cc3f70a9 100644
--- a/django/http/response.py
+++ b/django/http/response.py
@@ -246,8 +246,18 @@ class HttpResponse(HttpResponseBase):
else:
__str__ = serialize
+ def _consume_content(self):
+ # If the response was instantiated with an iterator, when its content
+ # is accessed, the iterator is going be exhausted and the content
+ # loaded in memory. At this point, it's better to abandon the original
+ # iterator and save the content for later reuse. This is a temporary
+ # solution. See the comment in __iter__ below for the long term plan.
+ if self._base_content_is_iter:
+ self.content = b''.join(self.make_bytes(e) for e in self._container)
+
@property
def content(self):
+ self._consume_content()
return b''.join(self.make_bytes(e) for e in self._container)
@content.setter
@@ -262,6 +272,17 @@ class HttpResponse(HttpResponseBase):
self._base_content_is_iter = False
def __iter__(self):
+ # Raise a deprecation warning only if the content wasn't consumed yet,
+ # because the response may be intended to be streamed.
+ # Once the deprecation completes, iterators should be consumed upon
+ # assignment rather than upon access. The _consume_content method
+ # should be removed. See #6527.
+ if self._base_content_is_iter:
+ warnings.warn(
+ 'Creating streaming responses with `HttpResponse` is '
+ 'deprecated. Use `StreamingHttpResponse` instead '
+ 'if you need the streaming behavior.',
+ PendingDeprecationWarning, stacklevel=2)
self._iterator = iter(self._container)
return self
@@ -277,14 +298,12 @@ class HttpResponse(HttpResponseBase):
next = __next__ # Python 2 compatibility
def write(self, content):
- if self._base_content_is_iter:
- raise Exception("This %s instance is not writable" % self.__class__.__name__)
+ self._consume_content()
self._container.append(content)
def tell(self):
- if self._base_content_is_iter:
- raise Exception("This %s instance cannot tell its position" % self.__class__.__name__)
- return sum([len(chunk) for chunk in self])
+ self._consume_content()
+ return sum(len(chunk) for chunk in self)
class StreamingHttpResponse(HttpResponseBase):
@@ -389,6 +408,7 @@ class HttpResponseNotModified(HttpResponse):
if value:
raise AttributeError("You cannot set content to a 304 (Not Modified) response")
self._container = []
+ self._base_content_is_iter = False
class HttpResponseBadRequest(HttpResponse):