From d861f95c445652e4269c9015836d14dcf8b9a587 Mon Sep 17 00:00:00 2001 From: Jon Dufresne Date: Mon, 12 Jan 2015 14:45:09 -0800 Subject: [PATCH] Fixed #24139 -- Changed HttpResponse.reason_phrase to evaluate based on status_code. --- django/http/response.py | 18 +++++++++++++----- docs/ref/request-response.txt | 18 ++++++++++++++++++ docs/releases/1.9.txt | 7 ++++++- tests/responses/tests.py | 6 ++++++ 4 files changed, 43 insertions(+), 6 deletions(-) diff --git a/django/http/response.py b/django/http/response.py index ce6b0344a73..c8d693085f1 100644 --- a/django/http/response.py +++ b/django/http/response.py @@ -37,7 +37,6 @@ class HttpResponseBase(six.Iterator): """ status_code = 200 - reason_phrase = None # Use default reason phrase for status code. def __init__(self, content_type=None, status=None, reason=None, charset=None): # _headers is a mapping of the lower-case name to the original case of @@ -52,16 +51,25 @@ class HttpResponseBase(six.Iterator): self.closed = False if status is not None: self.status_code = status - if reason is not None: - self.reason_phrase = reason - elif self.reason_phrase is None: - self.reason_phrase = responses.get(self.status_code, 'Unknown Status Code') + self._reason_phrase = reason self._charset = charset if content_type is None: content_type = '%s; charset=%s' % (settings.DEFAULT_CONTENT_TYPE, self.charset) self['Content-Type'] = content_type + @property + def reason_phrase(self): + if self._reason_phrase is not None: + return self._reason_phrase + # Leave self._reason_phrase unset in order to use the default + # reason phrase for status code. + return responses.get(self.status_code, 'Unknown Status Code') + + @reason_phrase.setter + def reason_phrase(self, value): + self._reason_phrase = value + @property def charset(self): if self._charset is not None: diff --git a/docs/ref/request-response.txt b/docs/ref/request-response.txt index 0a7a75cdc78..a555ba76eb3 100644 --- a/docs/ref/request-response.txt +++ b/docs/ref/request-response.txt @@ -631,6 +631,12 @@ Attributes The `HTTP status code`_ for the response. + .. versionchanged:: 1.9 + + Unless :attr:`reason_phrase` is explicitly set, modifying the value of + ``status_code`` outside the constructor will also modify the value of + ``reason_phrase``. + .. attribute:: HttpResponse.reason_phrase The HTTP reason phrase for the response. @@ -642,6 +648,9 @@ Attributes .. _`HTTP standard's`: https://www.ietf.org/rfc/rfc2616.txt + Unless explicitly set, ``reason_phrase`` is determined by the current + value of :attr:`status_code`. + .. attribute:: HttpResponse.streaming This is always ``False``. @@ -987,6 +996,12 @@ Attributes The `HTTP status code`_ for the response. + .. versionchanged:: 1.9 + + Unless :attr:`reason_phrase` is explicitly set, modifying the value of + ``status_code`` outside the constructor will also modify the value of + ``reason_phrase``. + .. attribute:: StreamingHttpResponse.reason_phrase The HTTP reason phrase for the response. @@ -998,6 +1013,9 @@ Attributes .. _`HTTP standard's`: https://www.ietf.org/rfc/rfc2616.txt + Unless explicitly set, ``reason_phrase`` is determined by the current + value of :attr:`status_code`. + .. attribute:: StreamingHttpResponse.streaming This is always ``True``. diff --git a/docs/releases/1.9.txt b/docs/releases/1.9.txt index 00ae10b56b7..da4984a9beb 100644 --- a/docs/releases/1.9.txt +++ b/docs/releases/1.9.txt @@ -163,7 +163,12 @@ Templates Requests and Responses ^^^^^^^^^^^^^^^^^^^^^^ -* ... +* Unless :attr:`HttpResponse.reason_phrase + ` is explicitly set, it now is + determined by the current value of :attr:`HttpResponse.status_code + `. Modifying the value of + ``status_code`` outside of the constructor will also modify the value of + ``reason_phrase``. Tests ^^^^^ diff --git a/tests/responses/tests.py b/tests/responses/tests.py index bf7a0e12efb..91ec710c721 100644 --- a/tests/responses/tests.py +++ b/tests/responses/tests.py @@ -54,6 +54,12 @@ class HttpResponseTests(SimpleTestCase): self.assertEqual(resp.status_code, 503) self.assertEqual(resp.reason_phrase, "Service Unavailable") + def test_change_status_code(self): + resp = HttpResponse() + resp.status_code = 503 + self.assertEqual(resp.status_code, 503) + self.assertEqual(resp.reason_phrase, "Service Unavailable") + def test_reason_phrase(self): reason = "I'm an anarchist coffee pot on crack." resp = HttpResponse(status=814, reason=reason)