summaryrefslogtreecommitdiff
path: root/django/db
diff options
context:
space:
mode:
authorSimon Charette <charette.s@gmail.com>2022-11-02 22:03:05 -0400
committerMariusz Felisiak <felisiak.mariusz@gmail.com>2022-12-01 19:14:00 +0100
commit0ff46591ac3010841c73fd26e0fef93995fedd99 (patch)
tree7373b7f028df958db09d353e603124bc52b37bed /django/db
parentd3e746ace5eeea07216da97d9c3801f2fdc43223 (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.py2
-rw-r--r--django/db/models/fields/__init__.py4
-rw-r--r--django/db/models/fields/json.py31
-rw-r--r--django/db/models/sql/compiler.py12
-rw-r--r--django/db/models/sql/query.py6
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))