Fixed #30294 -- Allowed HttpResponse to accept memoryview content.

This commit is contained in:
sage 2019-03-27 11:40:10 +07:00 committed by Tim Graham
parent 879cc3da62
commit 9aa56cb0d5
4 changed files with 22 additions and 8 deletions

View File

@ -229,7 +229,7 @@ class HttpResponseBase:
# Handle string types -- we can't rely on force_bytes here because: # Handle string types -- we can't rely on force_bytes here because:
# - Python attempts str conversion first # - Python attempts str conversion first
# - when self._charset != 'utf-8' it re-encodes the content # - when self._charset != 'utf-8' it re-encodes the content
if isinstance(value, bytes): if isinstance(value, (bytes, memoryview)):
return bytes(value) return bytes(value)
if isinstance(value, str): if isinstance(value, str):
return bytes(value.encode(self.charset)) return bytes(value.encode(self.charset))

View File

@ -631,13 +631,18 @@ Usage
Passing strings Passing strings
~~~~~~~~~~~~~~~ ~~~~~~~~~~~~~~~
Typical usage is to pass the contents of the page, as a string or bytestring, Typical usage is to pass the contents of the page, as a string, bytestring,
to the :class:`HttpResponse` constructor:: or :class:`memoryview`, to the :class:`HttpResponse` constructor::
>>> from django.http import HttpResponse >>> from django.http import HttpResponse
>>> response = HttpResponse("Here's the text of the Web page.") >>> response = HttpResponse("Here's the text of the Web page.")
>>> response = HttpResponse("Text only, please.", content_type="text/plain") >>> response = HttpResponse("Text only, please.", content_type="text/plain")
>>> response = HttpResponse(b'Bytestrings are also accepted.') >>> response = HttpResponse(b'Bytestrings are also accepted.')
>>> response = HttpResponse(memoryview(b'Memoryview as well.'))
.. versionchanged:: 3.0
Support for :class:`memoryview` was added.
But if you want to add content incrementally, you can use ``response`` as a But if you want to add content incrementally, you can use ``response`` as a
file-like object:: file-like object::
@ -741,10 +746,10 @@ Methods
Instantiates an ``HttpResponse`` object with the given page content and Instantiates an ``HttpResponse`` object with the given page content and
content type. content type.
``content`` is most commonly an iterator, bytestring, or string. Other ``content`` is most commonly an iterator, bytestring, :class:`memoryview`,
types will be converted to a bytestring by encoding their string or string. Other types will be converted to a bytestring by encoding their
representation. Iterators should return strings or bytestrings and those string representation. Iterators should return strings or bytestrings and
will be joined together to form the content of the response. those will be joined together to form the content of the response.
``content_type`` is the MIME type optionally completed by a character set ``content_type`` is the MIME type optionally completed by a character set
encoding and is used to fill the HTTP ``Content-Type`` header. If not encoding and is used to fill the HTTP ``Content-Type`` header. If not
@ -760,6 +765,10 @@ Methods
given it will be extracted from ``content_type``, and if that given it will be extracted from ``content_type``, and if that
is unsuccessful, the :setting:`DEFAULT_CHARSET` setting will be used. is unsuccessful, the :setting:`DEFAULT_CHARSET` setting will be used.
.. versionchanged:: 3.0
Support for :class:`memoryview` ``content`` was added.
.. method:: HttpResponse.__setitem__(header, value) .. method:: HttpResponse.__setitem__(header, value)
Sets the given header name to the given value. Both ``header`` and Sets the given header name to the given value. Both ``header`` and

View File

@ -188,7 +188,8 @@ Models
Requests and Responses Requests and Responses
~~~~~~~~~~~~~~~~~~~~~~ ~~~~~~~~~~~~~~~~~~~~~~
* ... * Allowed :class:`~django.http.HttpResponse` to be initialized with
:class:`memoryview` content.
Serialization Serialization
~~~~~~~~~~~~~ ~~~~~~~~~~~~~

View File

@ -366,6 +366,10 @@ class HttpResponseTests(unittest.TestCase):
r.content = 12345 r.content = 12345
self.assertEqual(r.content, b'12345') self.assertEqual(r.content, b'12345')
def test_memoryview_content(self):
r = HttpResponse(memoryview(b'memoryview'))
self.assertEqual(r.content, b'memoryview')
def test_iter_content(self): def test_iter_content(self):
r = HttpResponse(['abc', 'def', 'ghi']) r = HttpResponse(['abc', 'def', 'ghi'])
self.assertEqual(r.content, b'abcdefghi') self.assertEqual(r.content, b'abcdefghi')