diff options
| -rw-r--r-- | CHANGES.txt | 13 | ||||
| -rw-r--r-- | docs/api/request.rst | 10 | ||||
| -rw-r--r-- | docs/glossary.rst | 3 | ||||
| -rw-r--r-- | docs/narr/webob.rst | 55 | ||||
| -rw-r--r-- | docs/whatsnew-1.1.rst | 7 | ||||
| -rw-r--r-- | pyramid/request.py | 5 | ||||
| -rw-r--r-- | pyramid/tests/test_request.py | 21 |
7 files changed, 89 insertions, 25 deletions
diff --git a/CHANGES.txt b/CHANGES.txt index feabf0e26..ff4036036 100644 --- a/CHANGES.txt +++ b/CHANGES.txt @@ -9,10 +9,9 @@ Features object created by Pyramid. (See the Venusian documentation for more information about ``Scanner``). -- New request attribute: ``json``. If the request's ``content_type`` is - ``application/json``, this attribute will contain the JSON-decoded - variant of the request body. If the request's ``content_type`` is not - ``application/json``, this attribute will be ``None``. +- New request property: ``json_body``. This property will return the + JSON-decoded variant of the request body. If the request body is not + well-formed JSON, this property will raise an exception. - A new value ``http_cache`` can be used as a view configuration parameter. @@ -73,6 +72,12 @@ Bug Fixes IResponse. It wasn't always, because the response was resolved by the router instead of early in the view wrapping process. This has been fixed. +Documentation +------------- + +- Added a section in the "Webob" chapter named "Dealing With A JSON-Encoded + Request Body" (usage of ``request.json_body``). + 1.1a4 (2011-07-01) ================== diff --git a/docs/api/request.rst b/docs/api/request.rst index 5dfb2ae9a..404825d1b 100644 --- a/docs/api/request.rst +++ b/docs/api/request.rst @@ -180,12 +180,12 @@ object (exposed to view code as ``request.response``) to influence rendered response behavior. - .. attribute:: json + .. attribute:: json_body - If the request's ``content_type`` is ``application/json``, this - attribute will contain the JSON-decoded variant of the request body. - If the request's ``content_type`` is not ``application/json``, this - attribute will be ``None``. + This property will return the JSON-decoded variant of the request + body. If the request body is not well-formed JSON, or there is no + body associated with this request, this property will raise an + exception. See also :ref:`request_json_body`. .. note:: diff --git a/docs/glossary.rst b/docs/glossary.rst index e45317dae..c8943acae 100644 --- a/docs/glossary.rst +++ b/docs/glossary.rst @@ -506,6 +506,9 @@ Glossary `JavaScript Object Notation <http://www.json.org/>`_ is a data serialization format. + jQuery + A popular `Javascript library <http://jquery.org>`_. + renderer A serializer that can be referred to via :term:`view configuration` which converts a non-:term:`Response` return diff --git a/docs/narr/webob.rst b/docs/narr/webob.rst index 0ff8e1de7..373ae5896 100644 --- a/docs/narr/webob.rst +++ b/docs/narr/webob.rst @@ -78,6 +78,10 @@ object: ``PUT``. You can also get ``req.body_file`` for a file-like object. +``req.json_body`` + The JSON-decoded contents of the body of the request. See + :ref:`request_json_body`. + ``req.cookies``: A simple dictionary of all the cookies. @@ -239,6 +243,57 @@ tuples; all the keys are ordered, and all the values are ordered. API documentation for a multidict exists as :class:`pyramid.interfaces.IMultiDict`. +.. _request_json_body: + +Dealing With A JSON-Encoded Request Body +++++++++++++++++++++++++++++++++++++++++ + +.. note:: this feature is new as of Pyramid 1.1. + +:attr:`pyramid.request.Request.json_body` is a property that returns a +:term:`JSON` -decoded representation of the request body. If the request +does not have a body, or the body is not a properly JSON-encoded value, an +exception will be raised when this attribute is accessed. + +This attribute is useful when you invoke a Pyramid view callable via +e.g. jQuery's ``$.post`` or ``$.ajax`` functions, which have the potential to +send a JSON-encoded body or parameters. + +Using ``request.json_body`` is equivalent to: + +.. code-block:: python + + from json import loads + loads(request.body, encoding=request.charset) + +Here's how to construct an AJAX request in Javascript using :term:`jQuery` +that allows you to use the ``request.json_body`` attribute when the request +is sent to a Pyramid application: + +.. code-block:: javascript + + jQuery.ajax({type:'POST', + url: 'http://localhost:6543/', // the pyramid server + data: JSON.stringify({'a':1}), + contentType: 'application/json; charset=utf-8', + dataType: 'json'}); + +When such a request reaches a view in your application, the +``request.json_body`` attribute will be available in the view callable body. + +.. code-block:: javascript + + @view_config(renderer='json') + def aview(request): + print request.json_body + return {'result':'OK'} + +For the above view, printed to the console will be: + +.. code-block:: python + + {u'a': 1} + More Details ++++++++++++ diff --git a/docs/whatsnew-1.1.rst b/docs/whatsnew-1.1.rst index a6bb8e99d..a9df38a45 100644 --- a/docs/whatsnew-1.1.rst +++ b/docs/whatsnew-1.1.rst @@ -99,10 +99,9 @@ Minor Feature Additions the Venusian ``Scanner`` object created by Pyramid. (See the :term:`Venusian` documentation for more information about ``Scanner``). -- New request attribute: ``json``. If the request's ``content_type`` is - ``application/json``, this attribute will contain the JSON-decoded - variant of the request body. If the request's ``content_type`` is not - ``application/json``, this attribute will be ``None``. +- New request property: ``json_body``. This property will return the + JSON-decoded variant of the request body. If the request body is not + well-formed JSON, this property will raise an exception. - A new value ``http_cache`` can be used as a :term:`view configuration` parameter. diff --git a/pyramid/request.py b/pyramid/request.py index a3848461f..1bf044b69 100644 --- a/pyramid/request.py +++ b/pyramid/request.py @@ -491,9 +491,8 @@ class Request(BaseRequest, DeprecatedRequestMethods): return adapted is ob @property - def json(self): - if self.content_type == 'application/json': - return json.loads(self.body, encoding=self.charset) + def json_body(self): + return json.loads(self.body, encoding=self.charset) def route_request_iface(name, bases=()): diff --git a/pyramid/tests/test_request.py b/pyramid/tests/test_request.py index e65d484ed..74bc25359 100644 --- a/pyramid/tests/test_request.py +++ b/pyramid/tests/test_request.py @@ -233,25 +233,28 @@ class TestRequest(unittest.TestCase): request.registry.registerAdapter(adapter, (Foo,), IResponse) self.assertEqual(request.is_response(foo), True) - def test_json_incorrect_mimetype(self): - request = self._makeOne({}) - self.assertEqual(request.json, None) + def test_json_body_invalid_json(self): + request = self._makeOne({'REQUEST_METHOD':'POST'}) + request.body = '{' + self.assertRaises(ValueError, getattr, request, 'json_body') - def test_json_correct_mimetype(self): + def test_json_body_valid_json(self): request = self._makeOne({'REQUEST_METHOD':'POST'}) - request.content_type = 'application/json' request.body = '{"a":1}' - self.assertEqual(request.json, {'a':1}) + self.assertEqual(request.json_body, {'a':1}) - def test_json_alternate_charset(self): + def test_json_body_alternate_charset(self): from pyramid.compat import json request = self._makeOne({'REQUEST_METHOD':'POST'}) - request.content_type = 'application/json' request.charset = 'latin-1' la = unicode('La Pe\xc3\xb1a', 'utf-8') body = json.dumps({'a':la}, encoding='latin-1') request.body = body - self.assertEqual(request.json, {'a':la}) + self.assertEqual(request.json_body, {'a':la}) + + def test_json_body_GET_request(self): + request = self._makeOne({'REQUEST_METHOD':'GET'}) + self.assertRaises(ValueError, getattr, request, 'json_body') class TestRequestDeprecatedMethods(unittest.TestCase): def setUp(self): |
