diff --git a/django/http/__init__.py b/django/http/__init__.py index 2fe1247f657bf..a99c68045c5b5 100644 --- a/django/http/__init__.py +++ b/django/http/__init__.py @@ -373,8 +373,11 @@ def _get_codec(self): return self._codec def _set_codec(self, value): - if hasattr(value, "name"): - self._codec = value + if not hasattr(value, "name"): + # This is slightly more permissive, allowing any object with the + # "name" attribute. + raise Exception("Codec should be provided with a CodecInfo object.") + self._codec = value codec = property(_get_codec, _set_codec) diff --git a/tests/regressiontests/charsets/tests.py b/tests/regressiontests/charsets/tests.py index 580c71357adcd..c5f6a793e6c6f 100644 --- a/tests/regressiontests/charsets/tests.py +++ b/tests/regressiontests/charsets/tests.py @@ -16,12 +16,20 @@ def get_charset(response): class ClientTest(TestCase): urls = 'regressiontests.charsets.urls' - + test_string = u'\u82cf\u8054\u961f' + codec = get_codec("GBK") + + def encode(self, string): + return self.codec.encode(string)[0] + + def decode(self, string): + return self.codec.decode(string)[0] + def test_good_accept_charset(self): "Use Accept-Charset, with a quality value that throws away default_charset" # The data is ignored, but let's check it doesn't crash the system # anyway. - + response = self.client.post('/accept_charset/', ACCEPT_CHARSET="ascii,utf-8;q=0") self.assertEqual(response.status_code, 200) @@ -91,3 +99,27 @@ def test_basic_response(self): self.assertEqual(response.status_code, 200) self.assertEqual(get_charset(response), settings.DEFAULT_CHARSET) + def test_encode_content_type(self): + "Make sure a request gets encoded according to the content type in the view." + response = self.client.post('/encode_response_content_type/') + self.assertEqual(response.status_code, 200) + self.assertEqual(get_codec(get_charset(response)).name, self.codec.name) + self.assertEqual(response.content, self.encode(self.test_string)) + + def test_encode_accept_charset(self): + "Make sure a request gets encoded according to the Accept-Charset request header." + response = self.client.post('/encode_response_accept_charset/', + ACCEPT_CHARSET="gbk;q=1,utf-8;q=0.9") + + self.assertEqual(response.status_code, 200) + self.assertEqual(get_codec(get_charset(response)).name, self.codec.name) + self.assertEqual(response.content, self.encode(self.test_string)) + + def test_bad_codec(self): + "Assure we get an Exception for setting a bad codec in the view." + self.assertRaises(Exception, self.client.post, '/bad_codec/') + + def test_good_codecs(self): + response = self.client.post('/good_codec/') + self.assertEqual(response.status_code, 200) + self.assertEqual(response.content, self.encode(self.test_string)) diff --git a/tests/regressiontests/charsets/urls.py b/tests/regressiontests/charsets/urls.py index a54a11f62d86b..b03be9aeebf38 100644 --- a/tests/regressiontests/charsets/urls.py +++ b/tests/regressiontests/charsets/urls.py @@ -20,4 +20,8 @@ (r'^bad_content_type/', views.bad_content_type), (r'^content_type_no_charset/', views.content_type_no_charset), (r'^basic_response/', views.basic_response), + (r'^good_codec/', views.good_codec), + (r'^bad_codec/', views.bad_codec), + (r'^encode_response_content_type/', views.encode_response_content_type), + (r'^encode_response_accept_charset/', views.encode_response_accept_charset), ) diff --git a/tests/regressiontests/charsets/views.py b/tests/regressiontests/charsets/views.py index ea5258be4d2c4..e4e6915135509 100644 --- a/tests/regressiontests/charsets/views.py +++ b/tests/regressiontests/charsets/views.py @@ -1,6 +1,10 @@ +import codecs from django.http import HttpResponse from django.shortcuts import render_to_response +test_string = u'\u82cf\u8054\u961f' +codec = "GBK" + def accept_charset(request): return HttpResponse("ASCII.", request=request) @@ -13,8 +17,27 @@ def bad_content_type(request): def content_type_no_charset(request): return HttpResponse("UTF-8", content_type="text/html") -def encode_response(request): - return HttpResponse(u"\ue863", content_type="text/html; charset=GBK") +def encode_response_content_type(request): + return HttpResponse(test_string, content_type="text/html; charset=GBK") + +def encode_response_accept_charset(request): + return HttpResponse(test_string, request=request) def basic_response(request): return HttpResponse("ASCII.") + +# This mimics codecs.CodecInfo enough for the purposes of HttpResponse. +class FakeCodec: + def __init__(self, name=None): + if name: + self.name = name + +def bad_codec(request): + data = HttpResponse("ASCII.") + data.codec = FakeCodec() + return data + +def good_codec(request): + data = HttpResponse(test_string) + data.codec = FakeCodec(codec) + return data