Fixed #28370 -- Deprecated the context arg of Field.from_db_value() and Expression.convert_value().

Unused since a0d166306f.
This commit is contained in:
Tim Graham 2017-07-06 13:18:05 -04:00
parent 8d5095d8a3
commit 487362fa8f
28 changed files with 124 additions and 60 deletions

View File

@ -95,7 +95,7 @@ class MySQLOperations(BaseSpatialOperations, DatabaseOperations):
# https://dev.mysql.com/doc/refman/en/spatial-function-argument-handling.html # 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. # 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()': if value == b'GEOMETRYCOLLECTION()':
return b'GEOMETRYCOLLECTION EMPTY' return b'GEOMETRYCOLLECTION EMPTY'
return value return value

View File

@ -43,7 +43,7 @@ class Extent(GeoAggregate):
def __init__(self, expression, **extra): def __init__(self, expression, **extra):
super().__init__(expression, output_field=ExtentField(), **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) return connection.ops.convert_extent(value)
@ -54,7 +54,7 @@ class Extent3D(GeoAggregate):
def __init__(self, expression, **extra): def __init__(self, expression, **extra):
super().__init__(expression, output_field=ExtentField(), **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) return connection.ops.convert_extent3d(value)

View File

@ -255,7 +255,7 @@ class GeometryField(GeoSelectFormatMixin, BaseSpatialField):
kwargs['geography'] = self.geography kwargs['geography'] = self.geography
return name, path, args, kwargs return name, path, args, kwargs
def from_db_value(self, value, expression, connection, context): def from_db_value(self, value, expression, connection):
if value: if value:
value = Geometry(value) value = Geometry(value)
srid = value.srid srid = value.srid
@ -351,7 +351,7 @@ class RasterField(BaseSpatialField):
self._check_connection(connection) self._check_connection(connection)
return super().db_type(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) return connection.ops.parse_raster(value)
def contribute_to_class(self, cls, name, **kwargs): def contribute_to_class(self, cls, name, **kwargs):

View File

@ -23,7 +23,7 @@ class AreaField(models.FloatField):
return value return value
return getattr(value, self.area_att) 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 # If the database returns a Decimal, convert it to a float as expected
# by the Python geometric objects. # by the Python geometric objects.
if isinstance(value, Decimal): if isinstance(value, Decimal):
@ -54,7 +54,7 @@ class DistanceField(models.FloatField):
raise ValueError('Distance measure is supplied, but units are unknown for result.') raise ValueError('Distance measure is supplied, but units are unknown for result.')
return getattr(value, self.distance_att) 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: if value is None or not self.distance_att:
return value return value
return Distance(**{self.distance_att: value}) return Distance(**{self.distance_att: value})

View File

@ -13,7 +13,7 @@ class ArrayAgg(Aggregate):
def __init__(self, expression, distinct=False, **extra): def __init__(self, expression, distinct=False, **extra):
super().__init__(expression, distinct='DISTINCT ' if distinct else '', **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: if not value:
return [] return []
return value return value
@ -39,7 +39,7 @@ class JSONBAgg(Aggregate):
function = 'JSONB_AGG' function = 'JSONB_AGG'
output_field = JSONField() output_field = JSONField()
def convert_value(self, value, expression, connection, context): def convert_value(self, value, expression, connection):
if not value: if not value:
return [] return []
return value return value
@ -53,7 +53,7 @@ class StringAgg(Aggregate):
distinct = 'DISTINCT ' if distinct else '' distinct = 'DISTINCT ' if distinct else ''
super().__init__(expression, delimiter=delimiter, distinct=distinct, **extra) 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: if not value:
return '' return ''
return value return value

View File

@ -41,7 +41,7 @@ class RegrCount(StatAggregate):
def __init__(self, y, x): def __init__(self, y, x):
super().__init__(y=y, x=x, output_field=IntegerField()) 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: if value is None:
return 0 return 0
return int(value) return int(value)

View File

@ -6,6 +6,7 @@ from django.contrib.postgres.validators import ArrayMaxLengthValidator
from django.core import checks, exceptions from django.core import checks, exceptions
from django.db.models import Field, IntegerField, Transform from django.db.models import Field, IntegerField, Transform
from django.db.models.lookups import Exact, In 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 django.utils.translation import gettext_lazy as _
from ..utils import prefix_validation_error from ..utils import prefix_validation_error
@ -103,11 +104,13 @@ class ArrayField(Field):
value = [self.base_field.to_python(val) for val in vals] value = [self.base_field.to_python(val) for val in vals]
return value return value
def _from_db_value(self, value, expression, connection, context): def _from_db_value(self, value, expression, connection):
if value is None: if value is None:
return value return value
return [ 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 for item in value
] ]

View File

@ -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.db import DatabaseError, connections, models, router, transaction
from django.utils import timezone from django.utils import timezone
from django.utils.encoding import force_bytes from django.utils.encoding import force_bytes
from django.utils.inspect import func_supports_parameter
class Options: class Options:
@ -64,7 +65,10 @@ class DatabaseCache(BaseDatabaseCache):
expression = models.Expression(output_field=models.DateTimeField()) expression = models.Expression(output_field=models.DateTimeField())
for converter in (connection.ops.get_db_converters(expression) + for converter in (connection.ops.get_db_converters(expression) +
expression.get_db_converters(connection)): expression.get_db_converters(connection)):
if func_supports_parameter(converter, 'context'): # RemovedInDjango30Warning
expires = converter(expires, expression, connection, {}) expires = converter(expires, expression, connection, {})
else:
expires = converter(expires, expression, connection)
if expires < timezone.now(): if expires < timezone.now():
db = router.db_for_write(self.cache_model_class) db = router.db_for_write(self.cache_model_class)
@ -126,7 +130,10 @@ class DatabaseCache(BaseDatabaseCache):
expression = models.Expression(output_field=models.DateTimeField()) expression = models.Expression(output_field=models.DateTimeField())
for converter in (connection.ops.get_db_converters(expression) + for converter in (connection.ops.get_db_converters(expression) +
expression.get_db_converters(connection)): expression.get_db_converters(connection)):
if func_supports_parameter(converter, 'context'): # RemovedInDjango30Warning
current_expires = converter(current_expires, expression, connection, {}) current_expires = converter(current_expires, expression, connection, {})
else:
current_expires = converter(current_expires, expression, connection)
exp = connection.ops.adapt_datetimefield_value(exp) exp = connection.ops.adapt_datetimefield_value(exp)
if result and (mode == 'set' or (mode == 'add' and current_expires < now)): if result and (mode == 'set' or (mode == 'add' and current_expires < now)):

View File

@ -534,7 +534,7 @@ class BaseDatabaseOperations:
""" """
return [] return []
def convert_durationfield_value(self, value, expression, connection, context): def convert_durationfield_value(self, value, expression, connection):
if value is not None: if value is not None:
value = str(decimal.Decimal(value) / decimal.Decimal(1000000)) value = str(decimal.Decimal(value) / decimal.Decimal(1000000))
value = parse_duration(value) value = parse_duration(value)

View File

@ -221,23 +221,23 @@ class DatabaseOperations(BaseDatabaseOperations):
converters.append(self.convert_uuidfield_value) converters.append(self.convert_uuidfield_value)
return converters return converters
def convert_textfield_value(self, value, expression, connection, context): def convert_textfield_value(self, value, expression, connection):
if value is not None: if value is not None:
value = force_text(value) value = force_text(value)
return 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): if value in (0, 1):
value = bool(value) value = bool(value)
return 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 value is not None:
if settings.USE_TZ: if settings.USE_TZ:
value = timezone.make_aware(value, self.connection.timezone) value = timezone.make_aware(value, self.connection.timezone)
return 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: if value is not None:
value = uuid.UUID(value) value = uuid.UUID(value)
return value return value

View File

@ -165,17 +165,17 @@ END;
converters.append(self.convert_empty_values) converters.append(self.convert_empty_values)
return converters return converters
def convert_textfield_value(self, value, expression, connection, context): def convert_textfield_value(self, value, expression, connection):
if isinstance(value, Database.LOB): if isinstance(value, Database.LOB):
value = value.read() value = value.read()
return value return value
def convert_binaryfield_value(self, value, expression, connection, context): def convert_binaryfield_value(self, value, expression, connection):
if isinstance(value, Database.LOB): if isinstance(value, Database.LOB):
value = force_bytes(value.read()) value = force_bytes(value.read())
return 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): if value in (0, 1):
value = bool(value) value = bool(value)
return value return value
@ -184,28 +184,28 @@ END;
# DATE and TIMESTAMP columns, but Django wants to see a # DATE and TIMESTAMP columns, but Django wants to see a
# python datetime.date, .time, or .datetime. # 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 value is not None:
if settings.USE_TZ: if settings.USE_TZ:
value = timezone.make_aware(value, self.connection.timezone) value = timezone.make_aware(value, self.connection.timezone)
return value return value
def convert_datefield_value(self, value, expression, connection, context): def convert_datefield_value(self, value, expression, connection):
if isinstance(value, Database.Timestamp): if isinstance(value, Database.Timestamp):
value = value.date() value = value.date()
return value return value
def convert_timefield_value(self, value, expression, connection, context): def convert_timefield_value(self, value, expression, connection):
if isinstance(value, Database.Timestamp): if isinstance(value, Database.Timestamp):
value = value.time() value = value.time()
return 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: if value is not None:
value = uuid.UUID(value) value = uuid.UUID(value)
return 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 # Oracle stores empty strings as null. We need to undo this in
# order to adhere to the Django convention of using the empty # order to adhere to the Django convention of using the empty
# string instead of null, but only if the field accepts the # string instead of null, but only if the field accepts the

View File

@ -212,7 +212,7 @@ class DatabaseOperations(BaseDatabaseOperations):
converters.append(self.convert_booleanfield_value) converters.append(self.convert_booleanfield_value)
return converters 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 value is not None:
if not isinstance(value, datetime.datetime): if not isinstance(value, datetime.datetime):
value = parse_datetime(value) value = parse_datetime(value)
@ -220,30 +220,30 @@ class DatabaseOperations(BaseDatabaseOperations):
value = timezone.make_aware(value, self.connection.timezone) value = timezone.make_aware(value, self.connection.timezone)
return value 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 value is not None:
if not isinstance(value, datetime.date): if not isinstance(value, datetime.date):
value = parse_date(value) value = parse_date(value)
return 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 value is not None:
if not isinstance(value, datetime.time): if not isinstance(value, datetime.time):
value = parse_time(value) value = parse_time(value)
return 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: if value is not None:
value = expression.output_field.format_number(value) value = expression.output_field.format_number(value)
value = backend_utils.typecast_decimal(value) value = backend_utils.typecast_decimal(value)
return 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: if value is not None:
value = uuid.UUID(value) value = uuid.UUID(value)
return 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 return bool(value) if value in (1, 0) else value
def bulk_insert_sql(self, fields, placeholder_rows): def bulk_insert_sql(self, fields, placeholder_rows):

View File

@ -73,7 +73,7 @@ class Count(Aggregate):
def _get_repr_options(self): def _get_repr_options(self):
return {'distinct': self.extra['distinct'] != ''} return {'distinct': self.extra['distinct'] != ''}
def convert_value(self, value, expression, connection, context): def convert_value(self, value, expression, connection):
if value is None: if value is None:
return 0 return 0
return int(value) return int(value)
@ -99,7 +99,7 @@ class StdDev(Aggregate):
def _get_repr_options(self): def _get_repr_options(self):
return {'sample': self.function == 'STDDEV_SAMP'} 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: if value is None:
return value return value
return float(value) return float(value)
@ -129,7 +129,7 @@ class Variance(Aggregate):
def _get_repr_options(self): def _get_repr_options(self):
return {'sample': self.function == 'VAR_SAMP'} 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: if value is None:
return value return value
return float(value) return float(value)

View File

@ -261,7 +261,7 @@ class BaseExpression:
raise FieldError('Expression contains mixed types. You must set output_field.') raise FieldError('Expression contains mixed types. You must set output_field.')
return 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 Expressions provide their own converters because users have the option
of manually specifying the output_field which may be a different type of manually specifying the output_field which may be a different type

View File

@ -939,7 +939,7 @@ class ForeignKey(ForeignObject):
def db_parameters(self, connection): def db_parameters(self, connection):
return {"type": self.db_type(connection), "check": self.db_check(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): if (not value) and isinstance(value, str):
return None return None
return value return value

View File

@ -198,7 +198,7 @@ class TruncBase(TimezoneMixin, Transform):
)) ))
return copy return copy
def convert_value(self, value, expression, connection, context): def convert_value(self, value, expression, connection):
if isinstance(self.output_field, DateTimeField): if isinstance(self.output_field, DateTimeField):
if settings.USE_TZ: if settings.USE_TZ:
if value is None: if value is None:

View File

@ -1,5 +1,6 @@
import collections import collections
import re import re
import warnings
from itertools import chain from itertools import chain
from django.core.exceptions import EmptyResultSet, FieldError 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.models.sql.query import Query, get_order_dir
from django.db.transaction import TransactionManagementError from django.db.transaction import TransactionManagementError
from django.db.utils import DatabaseError, NotSupportedError from django.db.utils import DatabaseError, NotSupportedError
from django.utils.deprecation import RemovedInDjango30Warning
from django.utils.inspect import func_supports_parameter
FORCE = object() FORCE = object()
@ -926,7 +929,18 @@ class SQLCompiler:
for pos, (convs, expression) in converters.items(): for pos, (convs, expression) in converters.items():
value = row[pos] value = row[pos]
for converter in convs: 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 row[pos] = value
return tuple(row) return tuple(row)

View File

@ -46,7 +46,7 @@ def get_field_names_from_opts(opts):
class RawQuery: class RawQuery:
"""A single raw SQL query.""" """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.params = params or ()
self.sql = sql self.sql = sql
self.using = using self.using = using
@ -57,10 +57,9 @@ class RawQuery:
self.low_mark, self.high_mark = 0, None # Used for offset/limit self.low_mark, self.high_mark = 0, None # Used for offset/limit
self.extra_select = {} self.extra_select = {}
self.annotation_select = {} self.annotation_select = {}
self.context = context or {}
def clone(self, using): 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): def get_columns(self):
if self.cursor is None: if self.cursor is None:
@ -200,8 +199,6 @@ class Query:
# load. # load.
self.deferred_loading = (frozenset(), True) self.deferred_loading = (frozenset(), True)
self.context = {}
@property @property
def extra(self): def extra(self):
if self._extra is None: if self._extra is None:
@ -334,15 +331,8 @@ class Query:
obj.__dict__.update(kwargs) obj.__dict__.update(kwargs)
if hasattr(obj, '_setup_query'): if hasattr(obj, '_setup_query'):
obj._setup_query() obj._setup_query()
obj.context = self.context.copy()
return obj 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): def relabeled_clone(self, change_map):
clone = self.clone() clone = self.clone()
clone.change_aliases(change_map) clone.change_aliases(change_map)

View File

@ -512,7 +512,7 @@ instances::
class HandField(models.Field): 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: if value is None:
return value return value
return parse_hand(value) return parse_hand(value)

View File

@ -23,6 +23,9 @@ details on these changes.
* ``HttpRequest.xreadlines()`` will be removed. * ``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: .. _deprecation-removed-in-2.1:
2.1 2.1

View File

@ -714,7 +714,7 @@ calling the appropriate methods on the wrapped expression.
clone.expression = self.expression.relabeled_clone(change_map) clone.expression = self.expression.relabeled_clone(change_map)
return clone 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 A hook allowing the expression to coerce ``value`` into a more
appropriate type. appropriate type.

View File

@ -1797,7 +1797,7 @@ Field API reference
When loading data, :meth:`from_db_value` is used: 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 Converts a value as returned by the database to a Python object. It is
the reverse of :meth:`get_prep_value`. the reverse of :meth:`get_prep_value`.

View File

@ -564,6 +564,22 @@ Miscellaneous
Features deprecated in 2.0 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 Miscellaneous
------------- -------------

View File

@ -40,7 +40,7 @@ class MyAutoField(models.CharField):
value = MyWrapper(value) value = MyWrapper(value)
return value return value
def from_db_value(self, value, expression, connection, context): def from_db_value(self, value, expression, connection):
if not value: if not value:
return return
return MyWrapper(value) return MyWrapper(value)

View File

@ -17,7 +17,7 @@ class CashField(models.DecimalField):
kwargs['decimal_places'] = 2 kwargs['decimal_places'] = 2
super().__init__(**kwargs) super().__init__(**kwargs)
def from_db_value(self, value, expression, connection, context): def from_db_value(self, value, expression, connection):
cash = Cash(value) cash = Cash(value)
cash.vendor = connection.vendor cash.vendor = connection.vendor
return cash return cash
@ -28,3 +28,12 @@ class CashModel(models.Model):
def __str__(self): def __str__(self):
return str(self.cash) 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()

View File

@ -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.'
)

View File

@ -18,7 +18,7 @@ class Tag:
class TagField(models.SmallIntegerField): 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: if value is None:
return value return value
return Tag(int(value)) return Tag(int(value))

View File

@ -124,7 +124,7 @@ class TeamField(models.CharField):
return value return value
return Team(value) return Team(value)
def from_db_value(self, value, expression, connection, context): def from_db_value(self, value, expression, connection):
return Team(value) return Team(value)
def value_to_string(self, obj): def value_to_string(self, obj):