mirror of
				https://github.com/django/django.git
				synced 2025-10-31 09:41:08 +00:00 
			
		
		
		
	Refs #12990 -- Removed django.contrib.postgres.fields.JSONField per deprecation timeline.
This commit is contained in:
		| @@ -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', | ||||||
|     } |     } | ||||||
|  |  | ||||||
|  |  | ||||||
|   | |||||||
| @@ -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 | ||||||
| ~~~~~~~~~~~ | ~~~~~~~~~~~ | ||||||
|   | |||||||
| @@ -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 | ||||||
|   | |||||||
| @@ -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()``. | ||||||
|   | |||||||
| @@ -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`). | ||||||
|   | |||||||
| @@ -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`). | ||||||
|   | |||||||
| @@ -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`). | ||||||
|   | |||||||
| @@ -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. | ||||||
|  |  | ||||||
|   | |||||||
| @@ -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`. | ||||||
|  |  | ||||||
|   | |||||||
| @@ -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()``. | ||||||
|   | |||||||
| @@ -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`). | ||||||
|   | |||||||
| @@ -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`). | ||||||
|   | |||||||
| @@ -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`). | ||||||
|   | |||||||
| @@ -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. | ||||||
|  |  | ||||||
|   | |||||||
| @@ -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()``. | ||||||
|   | |||||||
| @@ -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`). | ||||||
|  |  | ||||||
|   | |||||||
| @@ -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`). | ||||||
|   | |||||||
| @@ -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 | ||||||
|   | |||||||
| @@ -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. | ||||||
|   | |||||||
| @@ -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', | ||||||
|  |             ), | ||||||
|  |         ]) | ||||||
|   | |||||||
| @@ -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 ' | ||||||
|   | |||||||
		Reference in New Issue
	
	Block a user