summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorTim Graham <timograham@gmail.com>2017-07-06 13:18:05 -0400
committerTim Graham <timograham@gmail.com>2017-07-20 16:30:08 -0400
commit487362fa8f23d41de4db58e7408e66eb36399af0 (patch)
tree25897a03c885d44a15860f59c121f0b6fab3e4a8
parent8d5095d8a33824e02c95ee44d6e5acdb4b39e7ed (diff)
Fixed #28370 -- Deprecated the context arg of Field.from_db_value() and Expression.convert_value().
Unused since a0d166306fbdc41f49e6fadf4ec84b17eb147daa.
-rw-r--r--django/contrib/gis/db/backends/mysql/operations.py2
-rw-r--r--django/contrib/gis/db/models/aggregates.py4
-rw-r--r--django/contrib/gis/db/models/fields.py4
-rw-r--r--django/contrib/gis/db/models/sql/conversion.py4
-rw-r--r--django/contrib/postgres/aggregates/general.py6
-rw-r--r--django/contrib/postgres/aggregates/statistics.py2
-rw-r--r--django/contrib/postgres/fields/array.py7
-rw-r--r--django/core/cache/backends/db.py11
-rw-r--r--django/db/backends/base/operations.py2
-rw-r--r--django/db/backends/mysql/operations.py8
-rw-r--r--django/db/backends/oracle/operations.py16
-rw-r--r--django/db/backends/sqlite3/operations.py12
-rw-r--r--django/db/models/aggregates.py6
-rw-r--r--django/db/models/expressions.py2
-rw-r--r--django/db/models/fields/related.py2
-rw-r--r--django/db/models/functions/datetime.py2
-rw-r--r--django/db/models/sql/compiler.py16
-rw-r--r--django/db/models/sql/query.py14
-rw-r--r--docs/howto/custom-model-fields.txt2
-rw-r--r--docs/internals/deprecation.txt3
-rw-r--r--docs/ref/models/expressions.txt2
-rw-r--r--docs/ref/models/fields.txt2
-rw-r--r--docs/releases/2.0.txt16
-rw-r--r--tests/custom_pk/fields.py2
-rw-r--r--tests/from_db_value/models.py11
-rw-r--r--tests/from_db_value/test_deprecated.py22
-rw-r--r--tests/postgres_tests/models.py2
-rw-r--r--tests/serializers/models/base.py2
28 files changed, 124 insertions, 60 deletions
diff --git a/django/contrib/gis/db/backends/mysql/operations.py b/django/contrib/gis/db/backends/mysql/operations.py
index b2ffd73928..786e8f887f 100644
--- a/django/contrib/gis/db/backends/mysql/operations.py
+++ b/django/contrib/gis/db/backends/mysql/operations.py
@@ -95,7 +95,7 @@ class MySQLOperations(BaseSpatialOperations, DatabaseOperations):
# https://dev.mysql.com/doc/refman/en/spatial-function-argument-handling.html
# MySQL 5.7.5 adds support for the empty geometry collections, but they are represented with invalid WKT.
- def convert_invalid_empty_geometry_collection(self, value, expression, connection, context):
+ def convert_invalid_empty_geometry_collection(self, value, expression, connection):
if value == b'GEOMETRYCOLLECTION()':
return b'GEOMETRYCOLLECTION EMPTY'
return value
diff --git a/django/contrib/gis/db/models/aggregates.py b/django/contrib/gis/db/models/aggregates.py
index 3fa57cdc07..3b5a89cafd 100644
--- a/django/contrib/gis/db/models/aggregates.py
+++ b/django/contrib/gis/db/models/aggregates.py
@@ -43,7 +43,7 @@ class Extent(GeoAggregate):
def __init__(self, expression, **extra):
super().__init__(expression, output_field=ExtentField(), **extra)
- def convert_value(self, value, expression, connection, context):
+ def convert_value(self, value, expression, connection):
return connection.ops.convert_extent(value)
@@ -54,7 +54,7 @@ class Extent3D(GeoAggregate):
def __init__(self, expression, **extra):
super().__init__(expression, output_field=ExtentField(), **extra)
- def convert_value(self, value, expression, connection, context):
+ def convert_value(self, value, expression, connection):
return connection.ops.convert_extent3d(value)
diff --git a/django/contrib/gis/db/models/fields.py b/django/contrib/gis/db/models/fields.py
index 0e79033374..bd1f427845 100644
--- a/django/contrib/gis/db/models/fields.py
+++ b/django/contrib/gis/db/models/fields.py
@@ -255,7 +255,7 @@ class GeometryField(GeoSelectFormatMixin, BaseSpatialField):
kwargs['geography'] = self.geography
return name, path, args, kwargs
- def from_db_value(self, value, expression, connection, context):
+ def from_db_value(self, value, expression, connection):
if value:
value = Geometry(value)
srid = value.srid
@@ -351,7 +351,7 @@ class RasterField(BaseSpatialField):
self._check_connection(connection)
return super().db_type(connection)
- def from_db_value(self, value, expression, connection, context):
+ def from_db_value(self, value, expression, connection):
return connection.ops.parse_raster(value)
def contribute_to_class(self, cls, name, **kwargs):
diff --git a/django/contrib/gis/db/models/sql/conversion.py b/django/contrib/gis/db/models/sql/conversion.py
index 3ba96a41cc..d9b79f237d 100644
--- a/django/contrib/gis/db/models/sql/conversion.py
+++ b/django/contrib/gis/db/models/sql/conversion.py
@@ -23,7 +23,7 @@ class AreaField(models.FloatField):
return value
return getattr(value, self.area_att)
- def from_db_value(self, value, expression, connection, context):
+ def from_db_value(self, value, expression, connection):
# If the database returns a Decimal, convert it to a float as expected
# by the Python geometric objects.
if isinstance(value, Decimal):
@@ -54,7 +54,7 @@ class DistanceField(models.FloatField):
raise ValueError('Distance measure is supplied, but units are unknown for result.')
return getattr(value, self.distance_att)
- def from_db_value(self, value, expression, connection, context):
+ def from_db_value(self, value, expression, connection):
if value is None or not self.distance_att:
return value
return Distance(**{self.distance_att: value})
diff --git a/django/contrib/postgres/aggregates/general.py b/django/contrib/postgres/aggregates/general.py
index 5bbf29e8ab..471eda2970 100644
--- a/django/contrib/postgres/aggregates/general.py
+++ b/django/contrib/postgres/aggregates/general.py
@@ -13,7 +13,7 @@ class ArrayAgg(Aggregate):
def __init__(self, expression, distinct=False, **extra):
super().__init__(expression, distinct='DISTINCT ' if distinct else '', **extra)
- def convert_value(self, value, expression, connection, context):
+ def convert_value(self, value, expression, connection):
if not value:
return []
return value
@@ -39,7 +39,7 @@ class JSONBAgg(Aggregate):
function = 'JSONB_AGG'
output_field = JSONField()
- def convert_value(self, value, expression, connection, context):
+ def convert_value(self, value, expression, connection):
if not value:
return []
return value
@@ -53,7 +53,7 @@ class StringAgg(Aggregate):
distinct = 'DISTINCT ' if distinct else ''
super().__init__(expression, delimiter=delimiter, distinct=distinct, **extra)
- def convert_value(self, value, expression, connection, context):
+ def convert_value(self, value, expression, connection):
if not value:
return ''
return value
diff --git a/django/contrib/postgres/aggregates/statistics.py b/django/contrib/postgres/aggregates/statistics.py
index ef6d172e57..b9a8ba07c5 100644
--- a/django/contrib/postgres/aggregates/statistics.py
+++ b/django/contrib/postgres/aggregates/statistics.py
@@ -41,7 +41,7 @@ class RegrCount(StatAggregate):
def __init__(self, y, x):
super().__init__(y=y, x=x, output_field=IntegerField())
- def convert_value(self, value, expression, connection, context):
+ def convert_value(self, value, expression, connection):
if value is None:
return 0
return int(value)
diff --git a/django/contrib/postgres/fields/array.py b/django/contrib/postgres/fields/array.py
index 18050e9a56..d418e1dc1a 100644
--- a/django/contrib/postgres/fields/array.py
+++ b/django/contrib/postgres/fields/array.py
@@ -6,6 +6,7 @@ from django.contrib.postgres.validators import ArrayMaxLengthValidator
from django.core import checks, exceptions
from django.db.models import Field, IntegerField, Transform
from django.db.models.lookups import Exact, In
+from django.utils.inspect import func_supports_parameter
from django.utils.translation import gettext_lazy as _
from ..utils import prefix_validation_error
@@ -103,11 +104,13 @@ class ArrayField(Field):
value = [self.base_field.to_python(val) for val in vals]
return value
- def _from_db_value(self, value, expression, connection, context):
+ def _from_db_value(self, value, expression, connection):
if value is None:
return value
return [
- self.base_field.from_db_value(item, expression, connection, context)
+ self.base_field.from_db_value(item, expression, connection, {})
+ if func_supports_parameter(self.base_field.from_db_value, 'context') # RemovedInDjango30Warning
+ else self.base_field.from_db_value(item, expression, connection)
for item in value
]
diff --git a/django/core/cache/backends/db.py b/django/core/cache/backends/db.py
index 50d897b621..576d711a67 100644
--- a/django/core/cache/backends/db.py
+++ b/django/core/cache/backends/db.py
@@ -8,6 +8,7 @@ from django.core.cache.backends.base import DEFAULT_TIMEOUT, BaseCache
from django.db import DatabaseError, connections, models, router, transaction
from django.utils import timezone
from django.utils.encoding import force_bytes
+from django.utils.inspect import func_supports_parameter
class Options:
@@ -64,7 +65,10 @@ class DatabaseCache(BaseDatabaseCache):
expression = models.Expression(output_field=models.DateTimeField())
for converter in (connection.ops.get_db_converters(expression) +
expression.get_db_converters(connection)):
- expires = converter(expires, expression, connection, {})
+ if func_supports_parameter(converter, 'context'): # RemovedInDjango30Warning
+ expires = converter(expires, expression, connection, {})
+ else:
+ expires = converter(expires, expression, connection)
if expires < timezone.now():
db = router.db_for_write(self.cache_model_class)
@@ -126,7 +130,10 @@ class DatabaseCache(BaseDatabaseCache):
expression = models.Expression(output_field=models.DateTimeField())
for converter in (connection.ops.get_db_converters(expression) +
expression.get_db_converters(connection)):
- current_expires = converter(current_expires, expression, connection, {})
+ if func_supports_parameter(converter, 'context'): # RemovedInDjango30Warning
+ current_expires = converter(current_expires, expression, connection, {})
+ else:
+ current_expires = converter(current_expires, expression, connection)
exp = connection.ops.adapt_datetimefield_value(exp)
if result and (mode == 'set' or (mode == 'add' and current_expires < now)):
diff --git a/django/db/backends/base/operations.py b/django/db/backends/base/operations.py
index 3e00f0cce0..dea15c2ad1 100644
--- a/django/db/backends/base/operations.py
+++ b/django/db/backends/base/operations.py
@@ -534,7 +534,7 @@ class BaseDatabaseOperations:
"""
return []
- def convert_durationfield_value(self, value, expression, connection, context):
+ def convert_durationfield_value(self, value, expression, connection):
if value is not None:
value = str(decimal.Decimal(value) / decimal.Decimal(1000000))
value = parse_duration(value)
diff --git a/django/db/backends/mysql/operations.py b/django/db/backends/mysql/operations.py
index e7fc2b93bf..405aa4bd45 100644
--- a/django/db/backends/mysql/operations.py
+++ b/django/db/backends/mysql/operations.py
@@ -221,23 +221,23 @@ class DatabaseOperations(BaseDatabaseOperations):
converters.append(self.convert_uuidfield_value)
return converters
- def convert_textfield_value(self, value, expression, connection, context):
+ def convert_textfield_value(self, value, expression, connection):
if value is not None:
value = force_text(value)
return value
- def convert_booleanfield_value(self, value, expression, connection, context):
+ def convert_booleanfield_value(self, value, expression, connection):
if value in (0, 1):
value = bool(value)
return value
- def convert_datetimefield_value(self, value, expression, connection, context):
+ def convert_datetimefield_value(self, value, expression, connection):
if value is not None:
if settings.USE_TZ:
value = timezone.make_aware(value, self.connection.timezone)
return value
- def convert_uuidfield_value(self, value, expression, connection, context):
+ def convert_uuidfield_value(self, value, expression, connection):
if value is not None:
value = uuid.UUID(value)
return value
diff --git a/django/db/backends/oracle/operations.py b/django/db/backends/oracle/operations.py
index 09c0e18d84..903bad3307 100644
--- a/django/db/backends/oracle/operations.py
+++ b/django/db/backends/oracle/operations.py
@@ -165,17 +165,17 @@ END;
converters.append(self.convert_empty_values)
return converters
- def convert_textfield_value(self, value, expression, connection, context):
+ def convert_textfield_value(self, value, expression, connection):
if isinstance(value, Database.LOB):
value = value.read()
return value
- def convert_binaryfield_value(self, value, expression, connection, context):
+ def convert_binaryfield_value(self, value, expression, connection):
if isinstance(value, Database.LOB):
value = force_bytes(value.read())
return value
- def convert_booleanfield_value(self, value, expression, connection, context):
+ def convert_booleanfield_value(self, value, expression, connection):
if value in (0, 1):
value = bool(value)
return value
@@ -184,28 +184,28 @@ END;
# DATE and TIMESTAMP columns, but Django wants to see a
# python datetime.date, .time, or .datetime.
- def convert_datetimefield_value(self, value, expression, connection, context):
+ def convert_datetimefield_value(self, value, expression, connection):
if value is not None:
if settings.USE_TZ:
value = timezone.make_aware(value, self.connection.timezone)
return value
- def convert_datefield_value(self, value, expression, connection, context):
+ def convert_datefield_value(self, value, expression, connection):
if isinstance(value, Database.Timestamp):
value = value.date()
return value
- def convert_timefield_value(self, value, expression, connection, context):
+ def convert_timefield_value(self, value, expression, connection):
if isinstance(value, Database.Timestamp):
value = value.time()
return value
- def convert_uuidfield_value(self, value, expression, connection, context):
+ def convert_uuidfield_value(self, value, expression, connection):
if value is not None:
value = uuid.UUID(value)
return value
- def convert_empty_values(self, value, expression, connection, context):
+ def convert_empty_values(self, value, expression, connection):
# Oracle stores empty strings as null. We need to undo this in
# order to adhere to the Django convention of using the empty
# string instead of null, but only if the field accepts the
diff --git a/django/db/backends/sqlite3/operations.py b/django/db/backends/sqlite3/operations.py
index 28db849828..f3c31ee1b9 100644
--- a/django/db/backends/sqlite3/operations.py
+++ b/django/db/backends/sqlite3/operations.py
@@ -212,7 +212,7 @@ class DatabaseOperations(BaseDatabaseOperations):
converters.append(self.convert_booleanfield_value)
return converters
- def convert_datetimefield_value(self, value, expression, connection, context):
+ def convert_datetimefield_value(self, value, expression, connection):
if value is not None:
if not isinstance(value, datetime.datetime):
value = parse_datetime(value)
@@ -220,30 +220,30 @@ class DatabaseOperations(BaseDatabaseOperations):
value = timezone.make_aware(value, self.connection.timezone)
return value
- def convert_datefield_value(self, value, expression, connection, context):
+ def convert_datefield_value(self, value, expression, connection):
if value is not None:
if not isinstance(value, datetime.date):
value = parse_date(value)
return value
- def convert_timefield_value(self, value, expression, connection, context):
+ def convert_timefield_value(self, value, expression, connection):
if value is not None:
if not isinstance(value, datetime.time):
value = parse_time(value)
return value
- def convert_decimalfield_value(self, value, expression, connection, context):
+ def convert_decimalfield_value(self, value, expression, connection):
if value is not None:
value = expression.output_field.format_number(value)
value = backend_utils.typecast_decimal(value)
return value
- def convert_uuidfield_value(self, value, expression, connection, context):
+ def convert_uuidfield_value(self, value, expression, connection):
if value is not None:
value = uuid.UUID(value)
return value
- def convert_booleanfield_value(self, value, expression, connection, context):
+ def convert_booleanfield_value(self, value, expression, connection):
return bool(value) if value in (1, 0) else value
def bulk_insert_sql(self, fields, placeholder_rows):
diff --git a/django/db/models/aggregates.py b/django/db/models/aggregates.py
index bc0f3d1916..2472a24663 100644
--- a/django/db/models/aggregates.py
+++ b/django/db/models/aggregates.py
@@ -73,7 +73,7 @@ class Count(Aggregate):
def _get_repr_options(self):
return {'distinct': self.extra['distinct'] != ''}
- def convert_value(self, value, expression, connection, context):
+ def convert_value(self, value, expression, connection):
if value is None:
return 0
return int(value)
@@ -99,7 +99,7 @@ class StdDev(Aggregate):
def _get_repr_options(self):
return {'sample': self.function == 'STDDEV_SAMP'}
- def convert_value(self, value, expression, connection, context):
+ def convert_value(self, value, expression, connection):
if value is None:
return value
return float(value)
@@ -129,7 +129,7 @@ class Variance(Aggregate):
def _get_repr_options(self):
return {'sample': self.function == 'VAR_SAMP'}
- def convert_value(self, value, expression, connection, context):
+ def convert_value(self, value, expression, connection):
if value is None:
return value
return float(value)
diff --git a/django/db/models/expressions.py b/django/db/models/expressions.py
index 52aebccb8e..dde39e80f0 100644
--- a/django/db/models/expressions.py
+++ b/django/db/models/expressions.py
@@ -261,7 +261,7 @@ class BaseExpression:
raise FieldError('Expression contains mixed types. You must set output_field.')
return output_field
- def convert_value(self, value, expression, connection, context):
+ def convert_value(self, value, expression, connection):
"""
Expressions provide their own converters because users have the option
of manually specifying the output_field which may be a different type
diff --git a/django/db/models/fields/related.py b/django/db/models/fields/related.py
index e92eca8fb4..50efa2974c 100644
--- a/django/db/models/fields/related.py
+++ b/django/db/models/fields/related.py
@@ -939,7 +939,7 @@ class ForeignKey(ForeignObject):
def db_parameters(self, connection):
return {"type": self.db_type(connection), "check": self.db_check(connection)}
- def convert_empty_strings(self, value, expression, connection, context):
+ def convert_empty_strings(self, value, expression, connection):
if (not value) and isinstance(value, str):
return None
return value
diff --git a/django/db/models/functions/datetime.py b/django/db/models/functions/datetime.py
index 52f1f73ae8..2c6d66d2e6 100644
--- a/django/db/models/functions/datetime.py
+++ b/django/db/models/functions/datetime.py
@@ -198,7 +198,7 @@ class TruncBase(TimezoneMixin, Transform):
))
return copy
- def convert_value(self, value, expression, connection, context):
+ def convert_value(self, value, expression, connection):
if isinstance(self.output_field, DateTimeField):
if settings.USE_TZ:
if value is None:
diff --git a/django/db/models/sql/compiler.py b/django/db/models/sql/compiler.py
index d53b9d1c5d..6e5ed79a41 100644
--- a/django/db/models/sql/compiler.py
+++ b/django/db/models/sql/compiler.py
@@ -1,5 +1,6 @@
import collections
import re
+import warnings
from itertools import chain
from django.core.exceptions import EmptyResultSet, FieldError
@@ -12,6 +13,8 @@ from django.db.models.sql.constants import (
from django.db.models.sql.query import Query, get_order_dir
from django.db.transaction import TransactionManagementError
from django.db.utils import DatabaseError, NotSupportedError
+from django.utils.deprecation import RemovedInDjango30Warning
+from django.utils.inspect import func_supports_parameter
FORCE = object()
@@ -926,7 +929,18 @@ class SQLCompiler:
for pos, (convs, expression) in converters.items():
value = row[pos]
for converter in convs:
- value = converter(value, expression, self.connection, self.query.context)
+ if func_supports_parameter(converter, 'context'):
+ warnings.warn(
+ 'Remove the context parameter from %s.%s(). Support for it '
+ 'will be removed in Django 3.0.' % (
+ converter.__self__.__class__.__name__,
+ converter.__name__,
+ ),
+ RemovedInDjango30Warning,
+ )
+ value = converter(value, expression, self.connection, {})
+ else:
+ value = converter(value, expression, self.connection)
row[pos] = value
return tuple(row)
diff --git a/django/db/models/sql/query.py b/django/db/models/sql/query.py
index 70ea85a275..c335d77c3c 100644
--- a/django/db/models/sql/query.py
+++ b/django/db/models/sql/query.py
@@ -46,7 +46,7 @@ def get_field_names_from_opts(opts):
class RawQuery:
"""A single raw SQL query."""
- def __init__(self, sql, using, params=None, context=None):
+ def __init__(self, sql, using, params=None):
self.params = params or ()
self.sql = sql
self.using = using
@@ -57,10 +57,9 @@ class RawQuery:
self.low_mark, self.high_mark = 0, None # Used for offset/limit
self.extra_select = {}
self.annotation_select = {}
- self.context = context or {}
def clone(self, using):
- return RawQuery(self.sql, using, params=self.params, context=self.context.copy())
+ return RawQuery(self.sql, using, params=self.params)
def get_columns(self):
if self.cursor is None:
@@ -200,8 +199,6 @@ class Query:
# load.
self.deferred_loading = (frozenset(), True)
- self.context = {}
-
@property
def extra(self):
if self._extra is None:
@@ -334,15 +331,8 @@ class Query:
obj.__dict__.update(kwargs)
if hasattr(obj, '_setup_query'):
obj._setup_query()
- obj.context = self.context.copy()
return obj
- def add_context(self, key, value):
- self.context[key] = value
-
- def get_context(self, key, default=None):
- return self.context.get(key, default)
-
def relabeled_clone(self, change_map):
clone = self.clone()
clone.change_aliases(change_map)
diff --git a/docs/howto/custom-model-fields.txt b/docs/howto/custom-model-fields.txt
index d7ad9562a5..8ecfee8709 100644
--- a/docs/howto/custom-model-fields.txt
+++ b/docs/howto/custom-model-fields.txt
@@ -512,7 +512,7 @@ instances::
class HandField(models.Field):
# ...
- def from_db_value(self, value, expression, connection, context):
+ def from_db_value(self, value, expression, connection):
if value is None:
return value
return parse_hand(value)
diff --git a/docs/internals/deprecation.txt b/docs/internals/deprecation.txt
index cee80fdbe2..c41245ac65 100644
--- a/docs/internals/deprecation.txt
+++ b/docs/internals/deprecation.txt
@@ -23,6 +23,9 @@ details on these changes.
* ``HttpRequest.xreadlines()`` will be removed.
+* Support for the ``context`` argument of ``Field.from_db_value()`` and
+ ``Expression.convert_value()`` will be removed.
+
.. _deprecation-removed-in-2.1:
2.1
diff --git a/docs/ref/models/expressions.txt b/docs/ref/models/expressions.txt
index 46dd5ecdd3..361b170412 100644
--- a/docs/ref/models/expressions.txt
+++ b/docs/ref/models/expressions.txt
@@ -714,7 +714,7 @@ calling the appropriate methods on the wrapped expression.
clone.expression = self.expression.relabeled_clone(change_map)
return clone
- .. method:: convert_value(value, expression, connection, context)
+ .. method:: convert_value(value, expression, connection)
A hook allowing the expression to coerce ``value`` into a more
appropriate type.
diff --git a/docs/ref/models/fields.txt b/docs/ref/models/fields.txt
index e9e601e5c7..90c64539f5 100644
--- a/docs/ref/models/fields.txt
+++ b/docs/ref/models/fields.txt
@@ -1797,7 +1797,7 @@ Field API reference
When loading data, :meth:`from_db_value` is used:
- .. method:: from_db_value(value, expression, connection, context)
+ .. method:: from_db_value(value, expression, connection)
Converts a value as returned by the database to a Python object. It is
the reverse of :meth:`get_prep_value`.
diff --git a/docs/releases/2.0.txt b/docs/releases/2.0.txt
index d90b80124d..16024ae244 100644
--- a/docs/releases/2.0.txt
+++ b/docs/releases/2.0.txt
@@ -564,6 +564,22 @@ Miscellaneous
Features deprecated in 2.0
==========================
+``context`` argument of ``Field.from_db_value()`` and ``Expression.convert_value()``
+------------------------------------------------------------------------------------
+
+The ``context`` argument of ``Field.from_db_value()`` and
+``Expression.convert_value()`` is unused as it's always an empty dictionary.
+The signature of both methods is now::
+
+ (self, value, expression, connection)
+
+instead of::
+
+ (self, value, expression, connection, context)
+
+Support for the old signature in custom fields and expressions remains until
+Django 3.0.
+
Miscellaneous
-------------
diff --git a/tests/custom_pk/fields.py b/tests/custom_pk/fields.py
index 78bb463fce..5bd249df3c 100644
--- a/tests/custom_pk/fields.py
+++ b/tests/custom_pk/fields.py
@@ -40,7 +40,7 @@ class MyAutoField(models.CharField):
value = MyWrapper(value)
return value
- def from_db_value(self, value, expression, connection, context):
+ def from_db_value(self, value, expression, connection):
if not value:
return
return MyWrapper(value)
diff --git a/tests/from_db_value/models.py b/tests/from_db_value/models.py
index 2f2304ff0a..3968a193d6 100644
--- a/tests/from_db_value/models.py
+++ b/tests/from_db_value/models.py
@@ -17,7 +17,7 @@ class CashField(models.DecimalField):
kwargs['decimal_places'] = 2
super().__init__(**kwargs)
- def from_db_value(self, value, expression, connection, context):
+ def from_db_value(self, value, expression, connection):
cash = Cash(value)
cash.vendor = connection.vendor
return cash
@@ -28,3 +28,12 @@ class CashModel(models.Model):
def __str__(self):
return str(self.cash)
+
+
+class CashFieldDeprecated(CashField):
+ def from_db_value(self, value, expression, connection, context):
+ return super().from_db_value(value, expression, connection)
+
+
+class CashModelDeprecated(models.Model):
+ cash = CashFieldDeprecated()
diff --git a/tests/from_db_value/test_deprecated.py b/tests/from_db_value/test_deprecated.py
new file mode 100644
index 0000000000..f0e7ed92b7
--- /dev/null
+++ b/tests/from_db_value/test_deprecated.py
@@ -0,0 +1,22 @@
+import warnings
+
+from django.test import TestCase
+
+from .models import Cash, CashModelDeprecated
+
+
+class FromDBValueDeprecationTests(TestCase):
+
+ def test_deprecation(self):
+ CashModelDeprecated.objects.create(cash='12.50')
+ with warnings.catch_warnings(record=True) as warns:
+ warnings.simplefilter('always')
+ instance = CashModelDeprecated.objects.get()
+ self.assertIsInstance(instance.cash, Cash)
+ self.assertEqual(len(warns), 1)
+ msg = str(warns[0].message)
+ self.assertEqual(
+ msg,
+ 'Remove the context parameter from CashFieldDeprecated.from_db_value(). '
+ 'Support for it will be removed in Django 3.0.'
+ )
diff --git a/tests/postgres_tests/models.py b/tests/postgres_tests/models.py
index fcfd85f8e7..b7094b77e1 100644
--- a/tests/postgres_tests/models.py
+++ b/tests/postgres_tests/models.py
@@ -18,7 +18,7 @@ class Tag:
class TagField(models.SmallIntegerField):
- def from_db_value(self, value, expression, connection, context):
+ def from_db_value(self, value, expression, connection):
if value is None:
return value
return Tag(int(value))
diff --git a/tests/serializers/models/base.py b/tests/serializers/models/base.py
index 2b7d18d93a..7d3a64452b 100644
--- a/tests/serializers/models/base.py
+++ b/tests/serializers/models/base.py
@@ -124,7 +124,7 @@ class TeamField(models.CharField):
return value
return Team(value)
- def from_db_value(self, value, expression, connection, context):
+ def from_db_value(self, value, expression, connection):
return Team(value)
def value_to_string(self, obj):