From 487362fa8f23d41de4db58e7408e66eb36399af0 Mon Sep 17 00:00:00 2001 From: Tim Graham Date: Thu, 6 Jul 2017 13:18:05 -0400 Subject: [PATCH] Fixed #28370 -- Deprecated the context arg of Field.from_db_value() and Expression.convert_value(). Unused since a0d166306fbdc41f49e6fadf4ec84b17eb147daa. --- .../gis/db/backends/mysql/operations.py | 2 +- django/contrib/gis/db/models/aggregates.py | 4 ++-- django/contrib/gis/db/models/fields.py | 4 ++-- .../contrib/gis/db/models/sql/conversion.py | 4 ++-- django/contrib/postgres/aggregates/general.py | 6 ++--- .../contrib/postgres/aggregates/statistics.py | 2 +- django/contrib/postgres/fields/array.py | 7 ++++-- django/core/cache/backends/db.py | 11 ++++++++-- django/db/backends/base/operations.py | 2 +- django/db/backends/mysql/operations.py | 8 +++---- django/db/backends/oracle/operations.py | 16 +++++++------- django/db/backends/sqlite3/operations.py | 12 +++++----- django/db/models/aggregates.py | 6 ++--- django/db/models/expressions.py | 2 +- django/db/models/fields/related.py | 2 +- django/db/models/functions/datetime.py | 2 +- django/db/models/sql/compiler.py | 16 +++++++++++++- django/db/models/sql/query.py | 14 ++---------- docs/howto/custom-model-fields.txt | 2 +- docs/internals/deprecation.txt | 3 +++ docs/ref/models/expressions.txt | 2 +- docs/ref/models/fields.txt | 2 +- docs/releases/2.0.txt | 16 ++++++++++++++ tests/custom_pk/fields.py | 2 +- tests/from_db_value/models.py | 11 +++++++++- tests/from_db_value/test_deprecated.py | 22 +++++++++++++++++++ tests/postgres_tests/models.py | 2 +- tests/serializers/models/base.py | 2 +- 28 files changed, 124 insertions(+), 60 deletions(-) create mode 100644 tests/from_db_value/test_deprecated.py 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):