Skip to content

Commit

Permalink
Fixed #25792 -- Renamed JsonResponse to JSONResponse
Browse files Browse the repository at this point in the history
Changed references to JsonResponse throughout the django project.
Added docs for deprecating JsonResponse.
Added test for deprecation warning.
  • Loading branch information
danifus committed Nov 21, 2015
1 parent ccc8f67 commit 9381fda
Show file tree
Hide file tree
Showing 12 changed files with 80 additions and 30 deletions.
6 changes: 3 additions & 3 deletions django/http/__init__.py
Original file line number Diff line number Diff line change
Expand Up @@ -7,7 +7,7 @@
HttpResponseBadRequest, HttpResponseForbidden, HttpResponseGone,
HttpResponseNotAllowed, HttpResponseNotFound, HttpResponseNotModified,
HttpResponsePermanentRedirect, HttpResponseRedirect,
HttpResponseServerError, JsonResponse, StreamingHttpResponse,
HttpResponseServerError, JsonResponse, JSONResponse, StreamingHttpResponse,
)

This comment has been minimized.

Copy link
@za

za Nov 22, 2015

@danifus Hi Dan, just wondering, why you didn't remove JsonResponse?

This comment has been minimized.

Copy link
@danifus

danifus Nov 22, 2015

Author Owner

Hi, I placed it in a deprecation cycle to give people using it a few releases (2 or 3 major point releases depending on the timing) to update their code before it is removed.

Check out line 521 of django/http/response.py to see where the deprecation warning is inserted.

This comment has been minimized.

Copy link
@za

za Nov 22, 2015

@danifus Ah, I see. Thanks Dan!

from django.http.utils import conditional_content_removal

Expand All @@ -18,6 +18,6 @@
'HttpResponsePermanentRedirect', 'HttpResponseNotModified',
'HttpResponseBadRequest', 'HttpResponseForbidden', 'HttpResponseNotFound',
'HttpResponseNotAllowed', 'HttpResponseGone', 'HttpResponseServerError',
'Http404', 'BadHeaderError', 'JsonResponse', 'FileResponse',
'conditional_content_removal',
'Http404', 'BadHeaderError', 'JsonResponse', 'JSONResponse',
'FileResponse', 'conditional_content_removal',
]
13 changes: 11 additions & 2 deletions django/http/response.py
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,7 @@
import re
import sys
import time
import warnings
from email.header import Header

from django.conf import settings
Expand All @@ -16,6 +17,7 @@
from django.utils.encoding import (
force_bytes, force_str, force_text, iri_to_uri,
)
from django.utils.deprecation import RemovedInDjango20Warning
from django.utils.http import cookie_date
from django.utils.six.moves import map
from django.utils.six.moves.http_client import responses
Expand Down Expand Up @@ -488,7 +490,7 @@ class Http404(Exception):
pass


class JsonResponse(HttpResponse):
class JSONResponse(HttpResponse):
"""
An HTTP response class that consumes data to be serialized to JSON.
Expand All @@ -511,4 +513,11 @@ def __init__(self, data, encoder=DjangoJSONEncoder, safe=True,
json_dumps_params = {}
kwargs.setdefault('content_type', 'application/json')
data = json.dumps(data, cls=encoder, **json_dumps_params)
super(JsonResponse, self).__init__(content=data, **kwargs)
super(JSONResponse, self).__init__(content=data, **kwargs)


class JsonResponse(JSONResponse):
def __init__(self, *args, **kwargs):
warnings.warn("`JsonResponse` is deprecated, use `JSONResponse` instead.",
RemovedInDjango20Warning)
super(JsonResponse, self).__init__(*args, **kwargs)
2 changes: 1 addition & 1 deletion django/views/i18n.py
Original file line number Diff line number Diff line change
Expand Up @@ -354,4 +354,4 @@ def json_catalog(request, domain='djangojs', packages=None):
'formats': get_formats(),
'plural': plural,
}
return http.JsonResponse(data)
return http.JSONResponse(data)
3 changes: 3 additions & 0 deletions docs/internals/deprecation.txt
Original file line number Diff line number Diff line change
Expand Up @@ -121,6 +121,9 @@ details on these changes.
* The ``get_coords()`` and ``set_coords()`` methods of
``django.contrib.gis.geos.Point`` will be removed.

* The backward compatible shim to rename ``django.http.JsonResponse`` to
:class:`~django.http.JSONResponse` will be removed.

.. _deprecation-removed-in-1.10:

1.10
Expand Down
24 changes: 19 additions & 5 deletions docs/ref/request-response.txt
Original file line number Diff line number Diff line change
Expand Up @@ -920,6 +920,16 @@ JsonResponse objects

.. class:: JsonResponse(data, encoder=DjangoJSONEncoder, safe=True, json_dumps_params=None, **kwargs)

.. deprecated:: 1.10

:class:`JsonResponse` has been renamed to :class:`JSONResponse`. Use
:class:`JSONResponse` instead.

JSONResponse objects
====================

.. class:: JSONResponse(data, encoder=DjangoJSONEncoder, safe=True, json_dumps_params=None, **kwargs)

An :class:`HttpResponse` subclass that helps to create a JSON-encoded
response. It inherits most behavior from its superclass with a couple
differences:
Expand Down Expand Up @@ -947,13 +957,17 @@ JsonResponse objects

The ``json_dumps_params`` argument was added.

.. versionchanged:: 1.10

This class replaced :class:`JsonResponse`.

Usage
-----

Typical usage could look like::

>>> from django.http import JsonResponse
>>> response = JsonResponse({'foo': 'bar'})
>>> from django.http import JSONResponse
>>> response = JSONResponse({'foo': 'bar'})
>>> response.content
b'{"foo": "bar"}'

Expand All @@ -964,7 +978,7 @@ Serializing non-dictionary objects
In order to serialize objects other than ``dict`` you must set the ``safe``
parameter to ``False``::

>>> response = JsonResponse([1, 2, 3], safe=False)
>>> response = JSONResponse([1, 2, 3], safe=False)

Without passing ``safe=False``, a :exc:`TypeError` will be raised.

Expand All @@ -974,7 +988,7 @@ Without passing ``safe=False``, a :exc:`TypeError` will be raised.
<http://www.ecma-international.org/publications/standards/Ecma-262.htm>`_
it was possible to poison the JavaScript ``Array`` constructor. For this
reason, Django does not allow passing non-dict objects to the
:class:`~django.http.JsonResponse` constructor by default. However, most
:class:`~django.http.JSONResponse` constructor by default. However, most
modern browsers implement EcmaScript 5 which removes this attack vector.
Therefore it is possible to disable this security precaution.

Expand All @@ -984,7 +998,7 @@ Changing the default JSON encoder
If you need to use a different JSON encoder class you can pass the ``encoder``
parameter to the constructor method::

>>> response = JsonResponse(data, encoder=MyJSONEncoder)
>>> response = JSONResponse(data, encoder=MyJSONEncoder)

.. _httpresponse-streaming:

Expand Down
8 changes: 8 additions & 0 deletions docs/releases/1.10.txt
Original file line number Diff line number Diff line change
Expand Up @@ -356,6 +356,14 @@ This prevents confusion about an assignment resulting in an implicit save.
:class:`~django.contrib.gis.geos.Point` are deprecated in favor of the
``tuple`` property.

:mod:`django.http`
~~~~~~~~~~~~~~~~~~

``django.http.JsonResponse`` has been renamed to
:class:`~django.http.JSONResponse` in order to bring the capitalization of
'JSON' inline with other references to JSON throughout the project.


Miscellaneous
~~~~~~~~~~~~~

Expand Down
6 changes: 3 additions & 3 deletions docs/topics/class-based-views/generic-editing.txt
Original file line number Diff line number Diff line change
Expand Up @@ -228,7 +228,7 @@ AJAX example
Here is a simple example showing how you might go about implementing a form that
works for AJAX requests as well as 'normal' form POSTs::

from django.http import JsonResponse
from django.http import JSONResponse
from django.views.generic.edit import CreateView
from myapp.models import Author

Expand All @@ -240,7 +240,7 @@ works for AJAX requests as well as 'normal' form POSTs::
def form_invalid(self, form):
response = super(AjaxableResponseMixin, self).form_invalid(form)
if self.request.is_ajax():
return JsonResponse(form.errors, status=400)
return JSONResponse(form.errors, status=400)
else:
return response

Expand All @@ -253,7 +253,7 @@ works for AJAX requests as well as 'normal' form POSTs::
data = {
'pk': self.object.pk,
}
return JsonResponse(data)
return JSONResponse(data)
else:
return response

Expand Down
4 changes: 2 additions & 2 deletions docs/topics/class-based-views/mixins.txt
Original file line number Diff line number Diff line change
Expand Up @@ -601,7 +601,7 @@ conversion to JSON once.

For example, a simple JSON mixin might look something like this::

from django.http import JsonResponse
from django.http import JSONResponse

class JSONResponseMixin(object):
"""
Expand All @@ -611,7 +611,7 @@ For example, a simple JSON mixin might look something like this::
"""
Returns a JSON response, transforming 'context' to make the payload.
"""
return JsonResponse(
return JSONResponse(
self.get_data(context),
**response_kwargs
)
Expand Down
34 changes: 25 additions & 9 deletions tests/httpwrappers/tests.py
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,7 @@
import pickle
import unittest
import uuid
import warnings

from django.core.exceptions import SuspiciousOperation
from django.core.serializers.json import DjangoJSONEncoder
Expand All @@ -15,7 +16,7 @@
from django.http import (
BadHeaderError, HttpResponse, HttpResponseNotAllowed,
HttpResponseNotModified, HttpResponsePermanentRedirect,
HttpResponseRedirect, JsonResponse, QueryDict, SimpleCookie,
HttpResponseRedirect, JsonResponse, JSONResponse, QueryDict, SimpleCookie,
StreamingHttpResponse, parse_cookie,
)
from django.test import SimpleTestCase
Expand Down Expand Up @@ -471,44 +472,59 @@ def test_not_allowed_repr(self):
self.assertEqual(repr(response), expected)


class JsonResponseTests(SimpleTestCase):
class JSONResponseTests(SimpleTestCase):

def test_json_response_non_ascii(self):
data = {'key': 'łóżko'}
response = JsonResponse(data)
response = JSONResponse(data)
self.assertEqual(json.loads(response.content.decode()), data)

def test_json_response_raises_type_error_with_default_setting(self):
with self.assertRaisesMessage(TypeError,
'In order to allow non-dict objects to be serialized set the '
'safe parameter to False'):
JsonResponse([1, 2, 3])
JSONResponse([1, 2, 3])

def test_json_response_text(self):
response = JsonResponse('foobar', safe=False)
response = JSONResponse('foobar', safe=False)
self.assertEqual(json.loads(response.content.decode()), 'foobar')

def test_json_response_list(self):
response = JsonResponse(['foo', 'bar'], safe=False)
response = JSONResponse(['foo', 'bar'], safe=False)
self.assertEqual(json.loads(response.content.decode()), ['foo', 'bar'])

def test_json_response_uuid(self):
u = uuid.uuid4()
response = JsonResponse(u, safe=False)
response = JSONResponse(u, safe=False)
self.assertEqual(json.loads(response.content.decode()), str(u))

def test_json_response_custom_encoder(self):
class CustomDjangoJSONEncoder(DjangoJSONEncoder):
def encode(self, o):
return json.dumps({'foo': 'bar'})

response = JsonResponse({}, encoder=CustomDjangoJSONEncoder)
response = JSONResponse({}, encoder=CustomDjangoJSONEncoder)
self.assertEqual(json.loads(response.content.decode()), {'foo': 'bar'})

def test_json_response_passing_arguments_to_json_dumps(self):
response = JsonResponse({'foo': 'bar'}, json_dumps_params={'indent': 2})
response = JSONResponse({'foo': 'bar'}, json_dumps_params={'indent': 2})
self.assertEqual(response.content.decode(), '{\n "foo": "bar"\n}')


class JsonResponseDeprecationTests(JSONResponseTests):

def test_json_response_deprecation_warning(self):
with warnings.catch_warnings(record=True) as warns:
# prevent warnings from appearing as errors
warnings.simplefilter('always')
data = {'key': 'łóżko'}
JsonResponse(data)

self.assertEqual(len(warns), 1)
msg = str(warns[0].message)
self.assertEqual(msg, "`JsonResponse` is deprecated, use `JSONResponse` instead.")


class StreamingHttpResponseTests(SimpleTestCase):
def test_streaming_response(self):
r = StreamingHttpResponse(iter(['hello', 'world']))
Expand Down
4 changes: 2 additions & 2 deletions tests/test_client_regress/views.py
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,7 @@
from django.conf import settings
from django.contrib.auth.decorators import login_required
from django.core.serializers.json import DjangoJSONEncoder
from django.http import HttpResponse, HttpResponseRedirect, JsonResponse
from django.http import HttpResponse, HttpResponseRedirect, JSONResponse
from django.shortcuts import render, render_to_response
from django.template.loader import render_to_string
from django.test import Client
Expand Down Expand Up @@ -108,7 +108,7 @@ def return_undecodable_binary(request):


def return_json_response(request):
return JsonResponse({'key': 'value'})
return JSONResponse({'key': 'value'})


def return_json_file(request):
Expand Down
2 changes: 1 addition & 1 deletion tests/view_tests/tests/test_json.py
Original file line number Diff line number Diff line change
Expand Up @@ -7,7 +7,7 @@


@override_settings(ROOT_URLCONF='view_tests.generic_urls')
class JsonResponseTests(SimpleTestCase):
class JSONResponseTests(SimpleTestCase):

def test_json_response(self):
response = self.client.get('/json/response/')
Expand Down
4 changes: 2 additions & 2 deletions tests/view_tests/views.py
Original file line number Diff line number Diff line change
Expand Up @@ -7,7 +7,7 @@

from django.core.exceptions import PermissionDenied, SuspiciousOperation
from django.core.urlresolvers import get_resolver
from django.http import Http404, HttpResponse, JsonResponse
from django.http import Http404, HttpResponse, JSONResponse
from django.shortcuts import render, render_to_response
from django.template import TemplateDoesNotExist
from django.views.debug import (
Expand Down Expand Up @@ -270,7 +270,7 @@ def multivalue_dict_key_error(request):


def json_response_view(request):
return JsonResponse({
return JSONResponse({
'a': [1, 2, 3],
'foo': {'bar': 'baz'},
# Make sure datetime and Decimal objects would be serialized properly
Expand Down

0 comments on commit 9381fda

Please sign in to comment.