Refs #12990 -- Removed django.contrib.postgres.fields.JSONField per deprecation timeline.

This commit is contained in:
Mariusz Felisiak 2021-01-14 09:33:12 +01:00
parent 98ae3925e5
commit 7cb5712edc
21 changed files with 45 additions and 93 deletions

View File

@ -11,14 +11,13 @@ __all__ = ['JSONField']
class JSONField(BuiltinJSONField): class JSONField(BuiltinJSONField):
system_check_deprecated_details = { system_check_removed_details = {
'msg': ( 'msg': (
'django.contrib.postgres.fields.JSONField is deprecated. Support ' 'django.contrib.postgres.fields.JSONField is removed except for '
'for it (except in historical migrations) will be removed in ' 'support in historical migrations.'
'Django 4.0.'
), ),
'hint': 'Use django.db.models.JSONField instead.', 'hint': 'Use django.db.models.JSONField instead.',
'id': 'fields.W904', 'id': 'fields.E904',
} }

View File

@ -212,7 +212,9 @@ Model fields
historical migrations. historical migrations.
* **fields.W904**: ``django.contrib.postgres.fields.JSONField`` is deprecated. * **fields.W904**: ``django.contrib.postgres.fields.JSONField`` is deprecated.
Support for it (except in historical migrations) will be removed in Django Support for it (except in historical migrations) will be removed in Django
4.0. 4.0. *This check appeared in Django 3.1 and 3.2*.
* **fields.E904**: ``django.contrib.postgres.fields.JSONField`` is removed
except for support in historical migrations.
File fields File fields
~~~~~~~~~~~ ~~~~~~~~~~~

View File

@ -482,59 +482,6 @@ using in conjunction with lookups on
>>> Dog.objects.filter(data__values__contains=['collie']) >>> Dog.objects.filter(data__values__contains=['collie'])
<QuerySet [<Dog: Meg>]> <QuerySet [<Dog: Meg>]>
``JSONField``
=============
.. class:: JSONField(encoder=None, **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``.
.. attribute:: encoder
An optional JSON-encoding class to serialize data types not supported
by the standard JSON serializer (``datetime``, ``uuid``, etc.). For
example, you can use the
:class:`~django.core.serializers.json.DjangoJSONEncoder` class or any
other :py:class:`json.JSONEncoder` subclass.
When the value is retrieved from the database, it will be in the format
chosen by the custom encoder (most often a string), so you'll need to
take extra steps to convert the value back to the initial data type
(:meth:`Model.from_db() <django.db.models.Model.from_db>` and
:meth:`Field.from_db_value() <django.db.models.Field.from_db_value>`
are two possible hooks for that purpose). Your deserialization may need
to account for the fact that you can't be certain of the input type.
For example, you run the risk of returning a ``datetime`` that was
actually a string that just happened to be in the same format chosen
for ``datetime``\s.
If you give the field a :attr:`~django.db.models.Field.default`, ensure
it's a callable such as ``dict`` (for an empty default) or a callable that
returns a dict (such as a function). Incorrectly using ``default={}``
creates a mutable default that is shared between all instances of
``JSONField``.
.. 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``.
.. deprecated:: 3.1
Use :class:`django.db.models.JSONField` instead.
Querying ``JSONField``
----------------------
See :ref:`querying-jsonfield` for details.
.. _range-fields: .. _range-fields:
Range Fields Range Fields

View File

@ -41,7 +41,7 @@ CVE-2019-14234: SQL injection possibility in key and index lookups for ``JSONFie
==================================================================================================== ====================================================================================================
:lookup:`Key and index lookups <jsonfield.key>` for :lookup:`Key and index lookups <jsonfield.key>` for
:class:`~django.contrib.postgres.fields.JSONField` and :lookup:`key lookups ``django.contrib.postgres.fields.JSONField`` and :lookup:`key lookups
<hstorefield.key>` for :class:`~django.contrib.postgres.fields.HStoreField` <hstorefield.key>` for :class:`~django.contrib.postgres.fields.HStoreField`
were subject to SQL injection, using a suitably crafted dictionary, with were subject to SQL injection, using a suitably crafted dictionary, with
dictionary expansion, as the ``**kwargs`` passed to ``QuerySet.filter()``. dictionary expansion, as the ``**kwargs`` passed to ``QuerySet.filter()``.

View File

@ -10,6 +10,6 @@ Bugfixes
======== ========
* Fixed crash of ``KeyTransform()`` for * Fixed crash of ``KeyTransform()`` for
:class:`~django.contrib.postgres.fields.JSONField` and ``django.contrib.postgres.fields.JSONField`` and
:class:`~django.contrib.postgres.fields.HStoreField` when using on :class:`~django.contrib.postgres.fields.HStoreField` when using on
expressions with params (:ticket:`30672`). expressions with params (:ticket:`30672`).

View File

@ -10,5 +10,5 @@ Bugfixes
======== ========
* Fixed a crash when filtering with a ``Subquery()`` annotation of a queryset * Fixed a crash when filtering with a ``Subquery()`` annotation of a queryset
containing :class:`~django.contrib.postgres.fields.JSONField` or containing ``django.contrib.postgres.fields.JSONField`` or
:class:`~django.contrib.postgres.fields.HStoreField` (:ticket:`30769`). :class:`~django.contrib.postgres.fields.HStoreField` (:ticket:`30769`).

View File

@ -11,5 +11,5 @@ Bugfixes
* Fixed a crash when using a ``contains``, ``contained_by``, ``has_key``, * Fixed a crash when using a ``contains``, ``contained_by``, ``has_key``,
``has_keys``, or ``has_any_keys`` lookup on ``has_keys``, or ``has_any_keys`` lookup on
:class:`~django.contrib.postgres.fields.JSONField`, if the right or left hand ``django.contrib.postgres.fields.JSONField``, if the right or left hand
side of an expression is a key transform (:ticket:`30826`). side of an expression is a key transform (:ticket:`30826`).

View File

@ -211,7 +211,7 @@ Minor features
:class:`~django.contrib.postgres.indexes.BrinIndex` classes allow :class:`~django.contrib.postgres.indexes.BrinIndex` classes allow
creating ``GIN`` and ``BRIN`` indexes in the database. creating ``GIN`` and ``BRIN`` indexes in the database.
* :class:`~django.contrib.postgres.fields.JSONField` accepts a new ``encoder`` * ``django.contrib.postgres.fields.JSONField`` accepts a new ``encoder``
parameter to specify a custom class to encode data types not supported by the parameter to specify a custom class to encode data types not supported by the
standard encoder. standard encoder.

View File

@ -265,7 +265,7 @@ Minor features
* Added support for the :lookup:`rangefield.contained_by` lookup for some built * Added support for the :lookup:`rangefield.contained_by` lookup for some built
in fields which correspond to the range fields. in fields which correspond to the range fields.
* Added :class:`~django.contrib.postgres.fields.JSONField`. * Added ``django.contrib.postgres.fields.JSONField``.
* Added :doc:`/ref/contrib/postgres/aggregates`. * Added :doc:`/ref/contrib/postgres/aggregates`.

View File

@ -41,7 +41,7 @@ CVE-2019-14234: SQL injection possibility in key and index lookups for ``JSONFie
==================================================================================================== ====================================================================================================
:lookup:`Key and index lookups <jsonfield.key>` for :lookup:`Key and index lookups <jsonfield.key>` for
:class:`~django.contrib.postgres.fields.JSONField` and :lookup:`key lookups ``django.contrib.postgres.fields.JSONField`` and :lookup:`key lookups
<hstorefield.key>` for :class:`~django.contrib.postgres.fields.HStoreField` <hstorefield.key>` for :class:`~django.contrib.postgres.fields.HStoreField`
were subject to SQL injection, using a suitably crafted dictionary, with were subject to SQL injection, using a suitably crafted dictionary, with
dictionary expansion, as the ``**kwargs`` passed to ``QuerySet.filter()``. dictionary expansion, as the ``**kwargs`` passed to ``QuerySet.filter()``.

View File

@ -10,6 +10,6 @@ Bugfixes
======== ========
* Fixed crash of ``KeyTransform()`` for * Fixed crash of ``KeyTransform()`` for
:class:`~django.contrib.postgres.fields.JSONField` and ``django.contrib.postgres.fields.JSONField`` and
:class:`~django.contrib.postgres.fields.HStoreField` when using on :class:`~django.contrib.postgres.fields.HStoreField` when using on
expressions with params (:ticket:`30672`). expressions with params (:ticket:`30672`).

View File

@ -10,5 +10,5 @@ Bugfixes
======== ========
* Fixed a crash when filtering with a ``Subquery()`` annotation of a queryset * Fixed a crash when filtering with a ``Subquery()`` annotation of a queryset
containing :class:`~django.contrib.postgres.fields.JSONField` or containing ``django.contrib.postgres.fields.JSONField`` or
:class:`~django.contrib.postgres.fields.HStoreField` (:ticket:`30769`). :class:`~django.contrib.postgres.fields.HStoreField` (:ticket:`30769`).

View File

@ -11,5 +11,5 @@ Bugfixes
* Fixed a crash when using a ``contains``, ``contained_by``, ``has_key``, * Fixed a crash when using a ``contains``, ``contained_by``, ``has_key``,
``has_keys``, or ``has_any_keys`` lookup on ``has_keys``, or ``has_any_keys`` lookup on
:class:`~django.contrib.postgres.fields.JSONField`, if the right or left hand ``django.contrib.postgres.fields.JSONField``, if the right or left hand
side of an expression is a key transform (:ticket:`30826`). side of an expression is a key transform (:ticket:`30826`).

View File

@ -373,7 +373,7 @@ Miscellaneous
* Since migrations are now loaded from ``.pyc`` files, you might need to delete * Since migrations are now loaded from ``.pyc`` files, you might need to delete
them if you're working in a mixed Python 2 and Python 3 environment. them if you're working in a mixed Python 2 and Python 3 environment.
* Using ``None`` as a :class:`~django.contrib.postgres.fields.JSONField` lookup * Using ``None`` as a ``django.contrib.postgres.fields.JSONField`` lookup
value now matches objects that have the specified key and a null value rather value now matches objects that have the specified key and a null value rather
than objects that don't have the key. than objects that don't have the key.

View File

@ -41,7 +41,7 @@ CVE-2019-14234: SQL injection possibility in key and index lookups for ``JSONFie
==================================================================================================== ====================================================================================================
:lookup:`Key and index lookups <jsonfield.key>` for :lookup:`Key and index lookups <jsonfield.key>` for
:class:`~django.contrib.postgres.fields.JSONField` and :lookup:`key lookups ``django.contrib.postgres.fields.JSONField`` and :lookup:`key lookups
<hstorefield.key>` for :class:`~django.contrib.postgres.fields.HStoreField` <hstorefield.key>` for :class:`~django.contrib.postgres.fields.HStoreField`
were subject to SQL injection, using a suitably crafted dictionary, with were subject to SQL injection, using a suitably crafted dictionary, with
dictionary expansion, as the ``**kwargs`` passed to ``QuerySet.filter()``. dictionary expansion, as the ``**kwargs`` passed to ``QuerySet.filter()``.

View File

@ -14,7 +14,7 @@ Bugfixes
(:ticket:`30673`). (:ticket:`30673`).
* Fixed crash of ``KeyTransform()`` for * Fixed crash of ``KeyTransform()`` for
:class:`~django.contrib.postgres.fields.JSONField` and ``django.contrib.postgres.fields.JSONField`` and
:class:`~django.contrib.postgres.fields.HStoreField` when using on :class:`~django.contrib.postgres.fields.HStoreField` when using on
expressions with params (:ticket:`30672`). expressions with params (:ticket:`30672`).

View File

@ -14,5 +14,5 @@ Bugfixes
* Fixed a regression in Django 2.2.4 that caused a crash when filtering with a * Fixed a regression in Django 2.2.4 that caused a crash when filtering with a
``Subquery()`` annotation of a queryset containing ``Subquery()`` annotation of a queryset containing
:class:`~django.contrib.postgres.fields.JSONField` or ``django.contrib.postgres.fields.JSONField`` or
:class:`~django.contrib.postgres.fields.HStoreField` (:ticket:`30769`). :class:`~django.contrib.postgres.fields.HStoreField` (:ticket:`30769`).

View File

@ -11,7 +11,7 @@ Bugfixes
* Fixed a crash when using a ``contains``, ``contained_by``, ``has_key``, * Fixed a crash when using a ``contains``, ``contained_by``, ``has_key``,
``has_keys``, or ``has_any_keys`` lookup on ``has_keys``, or ``has_any_keys`` lookup on
:class:`~django.contrib.postgres.fields.JSONField`, if the right or left hand ``django.contrib.postgres.fields.JSONField``, if the right or left hand
side of an expression is a key transform (:ticket:`30826`). side of an expression is a key transform (:ticket:`30826`).
* Prevented :option:`migrate --plan` from showing that ``RunPython`` operations * Prevented :option:`migrate --plan` from showing that ``RunPython`` operations

View File

@ -313,3 +313,6 @@ to remove usage of these features.
historical migrations. historical migrations.
* ``django.conf.urls.url()`` is removed. * ``django.conf.urls.url()`` is removed.
* The ``django.contrib.postgres.fields.JSONField`` model field is removed,
except for support in historical migrations.

View File

@ -1,5 +1,7 @@
from unittest import skipUnless
from django.core import checks from django.core import checks
from django.db import models from django.db import connection, models
from django.test import SimpleTestCase from django.test import SimpleTestCase
from django.test.utils import isolate_apps from django.test.utils import isolate_apps
@ -52,3 +54,20 @@ class DeprecatedFieldsTests(SimpleTestCase):
id='fields.E903', id='fields.E903',
), ),
]) ])
@skipUnless(connection.vendor == 'postgresql', 'PostgreSQL specific SQL')
def test_postgres_jsonfield_deprecated(self):
from django.contrib.postgres.fields import JSONField
class PostgresJSONFieldModel(models.Model):
field = JSONField()
self.assertEqual(PostgresJSONFieldModel.check(), [
checks.Error(
'django.contrib.postgres.fields.JSONField is removed except '
'for support in historical migrations.',
hint='Use django.db.models.JSONField instead.',
obj=PostgresJSONFieldModel._meta.get_field('field'),
id='fields.E904',
),
])

View File

@ -1,35 +1,17 @@
try: try:
from django.contrib.postgres import forms from django.contrib.postgres import forms
from django.contrib.postgres.fields import JSONField
from django.contrib.postgres.fields.jsonb import ( from django.contrib.postgres.fields.jsonb import (
KeyTextTransform, KeyTransform, KeyTextTransform, KeyTransform,
) )
except ImportError: except ImportError:
pass pass
from django.core.checks import Warning as DjangoWarning
from django.utils.deprecation import RemovedInDjango40Warning from django.utils.deprecation import RemovedInDjango40Warning
from . import PostgreSQLSimpleTestCase from . import PostgreSQLSimpleTestCase
from .models import PostgreSQLModel
class DeprecationTests(PostgreSQLSimpleTestCase): class DeprecationTests(PostgreSQLSimpleTestCase):
def test_model_field_deprecation_message(self):
class PostgreSQLJSONModel(PostgreSQLModel):
field = JSONField()
self.assertEqual(PostgreSQLJSONModel().check(), [
DjangoWarning(
'django.contrib.postgres.fields.JSONField is deprecated. '
'Support for it (except in historical migrations) will be '
'removed in Django 4.0.',
hint='Use django.db.models.JSONField instead.',
obj=PostgreSQLJSONModel._meta.get_field('field'),
id='fields.W904',
),
])
def test_form_field_deprecation_message(self): def test_form_field_deprecation_message(self):
msg = ( msg = (
'django.contrib.postgres.forms.JSONField is deprecated in favor ' 'django.contrib.postgres.forms.JSONField is deprecated in favor '