summaryrefslogtreecommitdiff
path: root/docs
diff options
context:
space:
mode:
Diffstat (limited to 'docs')
-rw-r--r--docs/ref/models/expressions.txt12
-rw-r--r--docs/releases/6.1.txt6
-rw-r--r--docs/topics/db/queries.txt39
3 files changed, 49 insertions, 8 deletions
diff --git a/docs/ref/models/expressions.txt b/docs/ref/models/expressions.txt
index fa5b4b9540..037d7520a3 100644
--- a/docs/ref/models/expressions.txt
+++ b/docs/ref/models/expressions.txt
@@ -575,6 +575,18 @@ available on other expressions. ``ExpressionWrapper`` is necessary when using
arithmetic on ``F()`` expressions with different types as described in
:ref:`using-f-with-annotations`.
+``JSONNull()`` expression
+-------------------------
+
+.. versionadded:: 6.1
+
+.. class:: JSONNull()
+
+Specialized expression to represent JSON scalar ``null`` on a
+:class:`~django.db.models.JSONField`.
+
+See :ref:`storing-and-querying-for-none` for usage examples.
+
Conditional expressions
-----------------------
diff --git a/docs/releases/6.1.txt b/docs/releases/6.1.txt
index 670026077a..bb8f686f84 100644
--- a/docs/releases/6.1.txt
+++ b/docs/releases/6.1.txt
@@ -238,6 +238,12 @@ Models
* :meth:`.QuerySet.in_bulk` now supports chaining after
:meth:`.QuerySet.values` and :meth:`.QuerySet.values_list`.
+* The new :class:`~django.db.models.JSONNull` expression provides an explicit
+ way to represent the JSON scalar ``null``. It can be used when saving a
+ top-level :class:`~django.db.models.JSONField` value, or querying for
+ top-level or nested JSON ``null`` values. See
+ :ref:`storing-and-querying-for-none` for usage examples and some caveats.
+
Pagination
~~~~~~~~~~
diff --git a/docs/topics/db/queries.txt b/docs/topics/db/queries.txt
index f6b8717f58..788a418e4f 100644
--- a/docs/topics/db/queries.txt
+++ b/docs/topics/db/queries.txt
@@ -1048,13 +1048,15 @@ the following example model::
def __str__(self):
return self.name
+.. _storing-and-querying-for-none:
+
Storing and querying for ``None``
---------------------------------
As with other fields, storing ``None`` as the field's value will store it as
SQL ``NULL``. While not recommended, it is possible to store JSON scalar
-``null`` instead of SQL ``NULL`` by using :class:`Value(None, JSONField())
-<django.db.models.Value>`.
+``null`` instead of SQL ``NULL`` by using the :class:`JSONNull()
+<django.db.models.JSONNull>` expression.
Whichever of the values is stored, when retrieved from the database, the Python
representation of the JSON scalar ``null`` is the same as SQL ``NULL``, i.e.
@@ -1064,18 +1066,21 @@ This only applies to ``None`` as the top-level value of the field. If ``None``
is inside a :class:`list` or :class:`dict`, it will always be interpreted
as JSON ``null``.
-When querying, ``None`` value will always be interpreted as JSON ``null``. To
-query for SQL ``NULL``, use :lookup:`isnull`:
+When querying, :lookup:`isnull=True <isnull>` is used to match SQL ``NULL``,
+while exact-matching ``JSONNull()`` is used to match JSON ``null``.
+
+.. versionchanged:: 6.1
+
+ ``JSONNull()`` expression was added.
.. code-block:: pycon
+ >>> from django.db.models import JSONNull
>>> Dog.objects.create(name="Max", data=None) # SQL NULL.
<Dog: Max>
- >>> Dog.objects.create(name="Archie", data=Value(None, JSONField())) # JSON null.
+ >>> Dog.objects.create(name="Archie", data=JSONNull()) # JSON null.
<Dog: Archie>
- >>> Dog.objects.filter(data=None)
- <QuerySet [<Dog: Archie>]>
- >>> Dog.objects.filter(data=Value(None, JSONField()))
+ >>> Dog.objects.filter(data=JSONNull())
<QuerySet [<Dog: Archie>]>
>>> Dog.objects.filter(data__isnull=True)
<QuerySet [<Dog: Max>]>
@@ -1091,6 +1096,14 @@ Unless you are sure you wish to work with SQL ``NULL`` values, consider setting
Storing JSON scalar ``null`` does not violate :attr:`null=False
<django.db.models.Field.null>`.
+.. admonition:: Storing JSON ``null`` inside JSON data
+
+ While :class:`JSONNull() <django.db.models.JSONNull>` can be used in
+ :lookup:`jsonfield.key` exact lookups, it cannot be stored inside
+ :class:`dict` or :class:`list` instances meant to be saved in a
+ ``JSONField``, unless a custom encoder is used. If you don't want to use
+ a custom encoder, use ``None`` instead.
+
.. fieldlookup:: jsonfield.key
.. _key-index-and-path-transforms:
@@ -1122,6 +1135,16 @@ To query based on a given dictionary key, use that key as the lookup name:
>>> Dog.objects.filter(data__breed="collie")
<QuerySet [<Dog: Meg>]>
+To query a key for JSON ``null``, ``None`` or :class:`JSONNull()
+<django.db.models.JSONNull>` can be used.
+
+.. code-block:: pycon
+
+ >>> Dog.objects.filter(data__owner=None)
+ <Dog: Meg>
+ >>> Dog.objects.filter(data__owner=JSONNull())
+ <Dog: Meg>
+
Multiple keys can be chained together to form a path lookup:
.. code-block:: pycon