load_json infrastructure for Morepath
Project description
more.body_model: ``load_json`` infrastructure for Morepath
==========================================================
The idea is to recognize on an application-level what kind of JSON content
is being posted, and convert it into a Python object. You can use this
application object with ``request.body_obj``. With ``body_model`` you can
then write views that specifically match that kind model.
To use it you have to subclass your application from
``more.body_model.BodyModelApp``:
.. code-block:: python
from more.body_model import BodyModelApp
class App(BodyModelApp):
pass
.. note:: If you want to use body_model on a mounted App, make sure that both,
the base App and the mounted App are a subclass from
``more.body_model.BodyModelApp``. Otherwise it will not work.
load_json
---------
The ``App.load_json`` directive lets you define a function that turns
incoming JSON into a Python object. This behavior is shared by all views in the
application. We detect JSON with the type field ``Item`` and interpret it as an
``Item`` instance, and pass through everything else:
.. code-block:: python
@App.load_json()
def load_json(json, request):
if json.get('type') != 'Item':
return json
return Item(json['x'])
When you write a ``json`` view you automatically get the ``Item``
instance as the ``body_obj`` attribute of the ``request``:
.. code-block:: python
@App.json(model=Collection, request_method='POST')
def collection_post(self, request):
collection.add(request.body_obj)
return "success!"
You can write views that match on the class of ``body_obj`` by specifying
``body_model``:
.. code-block:: python
@App.json(model=Collection, request_method='POST', body_model=Item)
def collection_post_item(self, request):
collection.add(request.body_obj)
return "success!"
body_model
----------
To define JSON body conversion code generally for an application we can use
``App.load_json``:
.. code-block:: python
@App.load_json()
def load_json(json, request):
if is_valid_document_json(json):
return Document(title=json['title'],
author=json['author'],
content=json['content'])
# fallback, just return plain JSON
return json
Now we get a ``Document`` instance in ``Request.body_obj``, so
we can simplify ``document_collection_post``:
.. code-block:: python
@App.json(model=DocumentCollection, request_method='POST')
def document_collection_post(self, request):
if not isinstance(request.body_obj, Document):
raise webob.exc.HTTPUnprocessableEntity()
result = self.add(request.body_obj)
return request.view(result)
To only match if ``body_obj`` is an instance of ``Document`` we can
use ``body_model`` on the view instead:
.. code-block:: python
@App.json(model=DocumentCollection, request_method='POST', body_model=Document)
def document_collection_post(self, request):
result = self.add(request.body_obj)
return request.view(result)
Now you get the ``422`` error for free if no matching ``body_model``
can be found. You can also create additional ``POST`` views for
``DocumentCollection`` that handle other types of JSON content this
way.
CHANGES
=======
0.1 (2017-03-17)
----------------
* initial public release.
==========================================================
The idea is to recognize on an application-level what kind of JSON content
is being posted, and convert it into a Python object. You can use this
application object with ``request.body_obj``. With ``body_model`` you can
then write views that specifically match that kind model.
To use it you have to subclass your application from
``more.body_model.BodyModelApp``:
.. code-block:: python
from more.body_model import BodyModelApp
class App(BodyModelApp):
pass
.. note:: If you want to use body_model on a mounted App, make sure that both,
the base App and the mounted App are a subclass from
``more.body_model.BodyModelApp``. Otherwise it will not work.
load_json
---------
The ``App.load_json`` directive lets you define a function that turns
incoming JSON into a Python object. This behavior is shared by all views in the
application. We detect JSON with the type field ``Item`` and interpret it as an
``Item`` instance, and pass through everything else:
.. code-block:: python
@App.load_json()
def load_json(json, request):
if json.get('type') != 'Item':
return json
return Item(json['x'])
When you write a ``json`` view you automatically get the ``Item``
instance as the ``body_obj`` attribute of the ``request``:
.. code-block:: python
@App.json(model=Collection, request_method='POST')
def collection_post(self, request):
collection.add(request.body_obj)
return "success!"
You can write views that match on the class of ``body_obj`` by specifying
``body_model``:
.. code-block:: python
@App.json(model=Collection, request_method='POST', body_model=Item)
def collection_post_item(self, request):
collection.add(request.body_obj)
return "success!"
body_model
----------
To define JSON body conversion code generally for an application we can use
``App.load_json``:
.. code-block:: python
@App.load_json()
def load_json(json, request):
if is_valid_document_json(json):
return Document(title=json['title'],
author=json['author'],
content=json['content'])
# fallback, just return plain JSON
return json
Now we get a ``Document`` instance in ``Request.body_obj``, so
we can simplify ``document_collection_post``:
.. code-block:: python
@App.json(model=DocumentCollection, request_method='POST')
def document_collection_post(self, request):
if not isinstance(request.body_obj, Document):
raise webob.exc.HTTPUnprocessableEntity()
result = self.add(request.body_obj)
return request.view(result)
To only match if ``body_obj`` is an instance of ``Document`` we can
use ``body_model`` on the view instead:
.. code-block:: python
@App.json(model=DocumentCollection, request_method='POST', body_model=Document)
def document_collection_post(self, request):
result = self.add(request.body_obj)
return request.view(result)
Now you get the ``422`` error for free if no matching ``body_model``
can be found. You can also create additional ``POST`` views for
``DocumentCollection`` that handle other types of JSON content this
way.
CHANGES
=======
0.1 (2017-03-17)
----------------
* initial public release.
Project details
Release history Release notifications | RSS feed
Download files
Download the file for your platform. If you're not sure which to choose, learn more about installing packages.
Source Distribution
more.body_model-0.1.tar.gz
(6.4 kB
view details)
Built Distribution
File details
Details for the file more.body_model-0.1.tar.gz
.
File metadata
- Download URL: more.body_model-0.1.tar.gz
- Upload date:
- Size: 6.4 kB
- Tags: Source
- Uploaded using Trusted Publishing? No
File hashes
Algorithm | Hash digest | |
---|---|---|
SHA256 | ddc1938f1f0ae92346902be45e6633e19029c77a4fce7a825ceb806bb47ad477 |
|
MD5 | 6c15dd38f6f9564e033fe95a6e0fda5c |
|
BLAKE2b-256 | cc1bca10b705c8474554c81121019f6d7b665b52aaafd7d3bfae0e0d35091f42 |
File details
Details for the file more.body_model-0.1-py2.py3-none-any.whl
.
File metadata
- Download URL: more.body_model-0.1-py2.py3-none-any.whl
- Upload date:
- Size: 8.7 kB
- Tags: Python 2, Python 3
- Uploaded using Trusted Publishing? No
File hashes
Algorithm | Hash digest | |
---|---|---|
SHA256 | 1ef87f3f07fea57060bc8741a9530c9cc572f8530f4fd494671455dd1b53c71d |
|
MD5 | f0a5daf1c36e4537d24aca2992c58987 |
|
BLAKE2b-256 | 7aa3f58feffa2904b34b2ec4b3d75442b1824721b9e543d9398b6057f6dfeb32 |