Fixed #24604 -- Added JSONField to contrib.postgres.

This commit is contained in:
Marc Tamlyn 2015-05-30 22:13:58 +01:00
parent 74fe4428e5
commit 33ea472f69
11 changed files with 540 additions and 3 deletions

View file

@ -450,6 +450,111 @@ using in conjunction with lookups on
>>> Dog.objects.filter(data__values__contains=['collie'])
[<Dog: Meg>]
JSONField
---------
.. versionadded:: 1.9
.. class:: JSONField(**options)
A field for storing JSON encoded data. In Python the data is represented in
its Python native format: dictionaries, lists, strings, numbers, booleans
and ``None``.
.. note::
PostgreSQL has two native JSON based data types: ``json`` and ``jsonb``.
The main difference between them is how they are stored and how they can be
queried. PostgreSQL's ``json`` field is stored as the original string
representation of the JSON and must be decoded on the fly when queried
based on keys. The ``jsonb`` field is stored based on the actual structure
of the JSON which allows indexing. The trade-off is a small additional cost
on writing to the ``jsonb`` field. ``JSONField`` uses ``jsonb``.
**As a result, the usage of this field is only supported on PostgreSQL
versions at least 9.4**.
Querying JSONField
^^^^^^^^^^^^^^^^^^
We will use the following example model::
from django.contrib.postgres.fields import JSONField
from django.db import models
class Dog(models.Model):
name = models.CharField(max_length=200)
data = JSONField()
def __str__(self): # __unicode__ on Python 2
return self.name
.. fieldlookup:: jsonfield.key
Key, index, and path lookups
~~~~~~~~~~~~~~~~~~~~~~~~~~~~
To query based on a given dictionary key, simply use that key as the lookup
name::
>>> Dog.objects.create(name='Rufus', data={
... 'breed': 'labrador',
... 'owner': {
... 'name': 'Bob',
... 'other_pets': [{
... 'name': 'Fishy',
... }],
... },
... })
>>> Dog.objects.create(name='Meg', data={'breed': 'collie'})
>>> Dog.objects.filter(data__breed='collie')
[<Dog: Meg>]
Multiple keys can be chained together to form a path lookup::
>>> Dog.objects.filter(data__owner__name='Bob')
[<Dog: Rufus>]
If the key is an integer, it will be interpreted as an index lookup in an
array::
>>> Dog.objects.filter(data__owner__other_pets__0__name='Fishy')
[<Dog: Rufus>]
If the key you wish to query by clashes with the name of another lookup, use
the :lookup:`jsonfield.contains` lookup instead.
If only one key or index is used, the SQL operator ``->`` is used. If multiple
operators are used then the ``#>`` operator is used.
.. warning::
Since any string could be a key in a JSON object, any lookup other than
those listed below will be interpreted as a key lookup. No errors are
raised. Be extra careful for typing mistakes, and always check your queries
work as you intend.
Containment and key operations
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
.. fieldlookup:: jsonfield.contains
.. fieldlookup:: jsonfield.contained_by
.. fieldlookup:: jsonfield.has_key
.. fieldlookup:: jsonfield.has_any_keys
.. fieldlookup:: jsonfield.has_keys
:class:`~django.contrib.postgres.fields.JSONField` shares lookups relating to
containment and keys with :class:`~django.contrib.postgres.fields.HStoreField`.
- :lookup:`contains <hstorefield.contains>` (accepts any JSON rather than
just a dictionary of strings)
- :lookup:`contained_by <hstorefield.contained_by>` (accepts any JSON
rather than just a dictionary of strings)
- :lookup:`has_key <hstorefield.has_key>`
- :lookup:`has_any_keys <hstorefield.has_any_keys>`
- :lookup:`has_keys <hstorefield.has_keys>`
.. _range-fields:
Range Fields

View file

@ -155,6 +155,21 @@ HStoreField
valid for a given field. This can be done using the
:class:`~django.contrib.postgres.validators.KeysValidator`.
JSONField
---------
.. class:: JSONField
A field which accepts JSON encoded data for a
:class:`~django.contrib.postgres.fields.JSONField`. It is represented by an
HTML ``<textarea>``.
.. admonition:: User friendly forms
``JSONField`` is not particularly user friendly in most cases, however
it is a useful way to format data from a client-side widget for
submission to the server.
Range Fields
------------

View file

@ -91,6 +91,7 @@ Minor features
:mod:`django.contrib.postgres`
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
* Added :class:`~django.contrib.postgres.fields.JSONField`.
* Added :doc:`/ref/contrib/postgres/aggregates`.
:mod:`django.contrib.redirects`