diff options
| author | Simon Charette <charette.s@gmail.com> | 2022-11-02 22:03:05 -0400 |
|---|---|---|
| committer | Mariusz Felisiak <felisiak.mariusz@gmail.com> | 2022-12-01 19:14:00 +0100 |
| commit | 0ff46591ac3010841c73fd26e0fef93995fedd99 (patch) | |
| tree | 7373b7f028df958db09d353e603124bc52b37bed /django/db | |
| parent | d3e746ace5eeea07216da97d9c3801f2fdc43223 (diff) | |
Refs #33308 -- Deprecated support for passing encoded JSON string literals to JSONField & co.
JSON should be provided as literal Python objects an not in their
encoded string literal forms.
Diffstat (limited to 'django/db')
| -rw-r--r-- | django/db/models/aggregates.py | 2 | ||||
| -rw-r--r-- | django/db/models/fields/__init__.py | 4 | ||||
| -rw-r--r-- | django/db/models/fields/json.py | 31 | ||||
| -rw-r--r-- | django/db/models/sql/compiler.py | 12 | ||||
| -rw-r--r-- | django/db/models/sql/query.py | 6 |
5 files changed, 41 insertions, 14 deletions
diff --git a/django/db/models/aggregates.py b/django/db/models/aggregates.py index e2e0ef762b..e672f0aeb0 100644 --- a/django/db/models/aggregates.py +++ b/django/db/models/aggregates.py @@ -85,6 +85,8 @@ class Aggregate(Func): return c if hasattr(default, "resolve_expression"): default = default.resolve_expression(query, allow_joins, reuse, summarize) + if default._output_field_or_none is None: + default.output_field = c._output_field_or_none else: default = Value(default, c._output_field_or_none) c.default = None # Reset the default argument before wrapping. diff --git a/django/db/models/fields/__init__.py b/django/db/models/fields/__init__.py index 2a98396cad..cd995de80f 100644 --- a/django/db/models/fields/__init__.py +++ b/django/db/models/fields/__init__.py @@ -921,6 +921,8 @@ class Field(RegisterLookupMixin): def get_db_prep_save(self, value, connection): """Return field's value prepared for saving into a database.""" + if hasattr(value, "as_sql"): + return value return self.get_db_prep_value(value, connection=connection, prepared=False) def has_default(self): @@ -1715,6 +1717,8 @@ class DecimalField(Field): def get_db_prep_value(self, value, connection, prepared=False): if not prepared: value = self.get_prep_value(value) + if hasattr(value, "as_sql"): + return value return connection.ops.adapt_decimalfield_value( value, self.max_digits, self.decimal_places ) diff --git a/django/db/models/fields/json.py b/django/db/models/fields/json.py index c0242bd7be..eb2d35f100 100644 --- a/django/db/models/fields/json.py +++ b/django/db/models/fields/json.py @@ -1,9 +1,10 @@ import json +import warnings from django import forms from django.core import checks, exceptions from django.db import NotSupportedError, connections, router -from django.db.models import lookups +from django.db.models import expressions, lookups from django.db.models.constants import LOOKUP_SEP from django.db.models.fields import TextField from django.db.models.lookups import ( @@ -11,6 +12,7 @@ from django.db.models.lookups import ( PostgresOperatorLookup, Transform, ) +from django.utils.deprecation import RemovedInDjango51Warning from django.utils.translation import gettext_lazy as _ from . import Field @@ -97,7 +99,32 @@ class JSONField(CheckFieldDefaultMixin, Field): return "JSONField" def get_db_prep_value(self, value, connection, prepared=False): - if hasattr(value, "as_sql"): + # RemovedInDjango51Warning: When the deprecation ends, replace with: + # if ( + # isinstance(value, expressions.Value) + # and isinstance(value.output_field, JSONField) + # ): + # value = value.value + # elif hasattr(value, "as_sql"): ... + if isinstance(value, expressions.Value): + if isinstance(value.value, str) and not isinstance( + value.output_field, JSONField + ): + try: + value = json.loads(value.value, cls=self.decoder) + except json.JSONDecodeError: + value = value.value + else: + warnings.warn( + "Providing an encoded JSON string via Value() is deprecated. " + f"Use Value({value!r}, output_field=JSONField()) instead.", + category=RemovedInDjango51Warning, + ) + elif isinstance(value.output_field, JSONField): + value = value.value + else: + return value + elif hasattr(value, "as_sql"): return value return connection.ops.adapt_json_value(value, self.encoder) diff --git a/django/db/models/sql/compiler.py b/django/db/models/sql/compiler.py index caf36382b5..2b66ab12b4 100644 --- a/django/db/models/sql/compiler.py +++ b/django/db/models/sql/compiler.py @@ -1637,9 +1637,7 @@ class SQLInsertCompiler(SQLCompiler): "Window expressions are not allowed in this query (%s=%r)." % (field.name, value) ) - else: - value = field.get_db_prep_save(value, connection=self.connection) - return value + return field.get_db_prep_save(value, connection=self.connection) def pre_save_val(self, field, obj): """ @@ -1893,18 +1891,14 @@ class SQLUpdateCompiler(SQLCompiler): ) elif hasattr(val, "prepare_database_save"): if field.remote_field: - val = field.get_db_prep_save( - val.prepare_database_save(field), - connection=self.connection, - ) + val = val.prepare_database_save(field) else: raise TypeError( "Tried to update field %s with a model instance, %r. " "Use a value compatible with %s." % (field, val, field.__class__.__name__) ) - else: - val = field.get_db_prep_save(val, connection=self.connection) + val = field.get_db_prep_save(val, connection=self.connection) # Getting the placeholder for the field. if hasattr(field, "get_placeholder"): diff --git a/django/db/models/sql/query.py b/django/db/models/sql/query.py index 521054f69e..9e70aadca1 100644 --- a/django/db/models/sql/query.py +++ b/django/db/models/sql/query.py @@ -522,9 +522,9 @@ class Query(BaseExpression): result = compiler.execute_sql(SINGLE) if result is None: result = empty_set_result - - converters = compiler.get_converters(outer_query.annotation_select.values()) - result = next(compiler.apply_converters((result,), converters)) + else: + converters = compiler.get_converters(outer_query.annotation_select.values()) + result = next(compiler.apply_converters((result,), converters)) return dict(zip(outer_query.annotation_select, result)) |
