mirror of https://github.com/django/django.git
Update converters to take a consistent set of parameters.
As suggested by Anssi. This has the slightly strange side effect of passing the expression to Expression.convert_value has the expression passed back to it, but it allows more complex patterns of expressions.
This commit is contained in:
parent
4755f8fc25
commit
32d4db66b9
|
@ -127,7 +127,7 @@ class OracleOperations(BaseSpatialOperations, DatabaseOperations):
|
||||||
converters.append(self.convert_geometry)
|
converters.append(self.convert_geometry)
|
||||||
return converters
|
return converters
|
||||||
|
|
||||||
def convert_geometry(self, value, expression, context):
|
def convert_geometry(self, value, expression, connection, context):
|
||||||
if value:
|
if value:
|
||||||
value = Geometry(value)
|
value = Geometry(value)
|
||||||
if 'transformed_srid' in context:
|
if 'transformed_srid' in context:
|
||||||
|
|
|
@ -262,7 +262,7 @@ class SpatiaLiteOperations(BaseSpatialOperations, DatabaseOperations):
|
||||||
converters.append(self.convert_geometry)
|
converters.append(self.convert_geometry)
|
||||||
return converters
|
return converters
|
||||||
|
|
||||||
def convert_geometry(self, value, expression, context):
|
def convert_geometry(self, value, expression, connection, context):
|
||||||
if value:
|
if value:
|
||||||
value = Geometry(value)
|
value = Geometry(value)
|
||||||
if 'transformed_srid' in context:
|
if 'transformed_srid' in context:
|
||||||
|
|
|
@ -29,7 +29,7 @@ class GeoAggregate(Aggregate):
|
||||||
raise ValueError('Geospatial aggregates only allowed on geometry fields.')
|
raise ValueError('Geospatial aggregates only allowed on geometry fields.')
|
||||||
return c
|
return c
|
||||||
|
|
||||||
def convert_value(self, value, connection, context):
|
def convert_value(self, value, expression, connection, context):
|
||||||
return connection.ops.convert_geom(value, self.output_field)
|
return connection.ops.convert_geom(value, self.output_field)
|
||||||
|
|
||||||
|
|
||||||
|
@ -44,7 +44,7 @@ class Extent(GeoAggregate):
|
||||||
def __init__(self, expression, **extra):
|
def __init__(self, expression, **extra):
|
||||||
super(Extent, self).__init__(expression, output_field=ExtentField(), **extra)
|
super(Extent, self).__init__(expression, output_field=ExtentField(), **extra)
|
||||||
|
|
||||||
def convert_value(self, value, connection, context):
|
def convert_value(self, value, expression, connection, context):
|
||||||
return connection.ops.convert_extent(value, context.get('transformed_srid'))
|
return connection.ops.convert_extent(value, context.get('transformed_srid'))
|
||||||
|
|
||||||
|
|
||||||
|
@ -55,7 +55,7 @@ class Extent3D(GeoAggregate):
|
||||||
def __init__(self, expression, **extra):
|
def __init__(self, expression, **extra):
|
||||||
super(Extent3D, self).__init__(expression, output_field=ExtentField(), **extra)
|
super(Extent3D, self).__init__(expression, output_field=ExtentField(), **extra)
|
||||||
|
|
||||||
def convert_value(self, value, connection, context):
|
def convert_value(self, value, expression, connection, context):
|
||||||
return connection.ops.convert_extent3d(value, context.get('transformed_srid'))
|
return connection.ops.convert_extent3d(value, context.get('transformed_srid'))
|
||||||
|
|
||||||
|
|
||||||
|
|
|
@ -219,7 +219,7 @@ class GeometryField(GeoSelectFormatMixin, Field):
|
||||||
else:
|
else:
|
||||||
return geom
|
return geom
|
||||||
|
|
||||||
def from_db_value(self, value, connection, context):
|
def from_db_value(self, value, expression, connection, context):
|
||||||
if value and not isinstance(value, Geometry):
|
if value and not isinstance(value, Geometry):
|
||||||
value = Geometry(value)
|
value = Geometry(value)
|
||||||
return value
|
return value
|
||||||
|
|
|
@ -23,7 +23,7 @@ class AreaField(BaseField):
|
||||||
def __init__(self, area_att):
|
def __init__(self, area_att):
|
||||||
self.area_att = area_att
|
self.area_att = area_att
|
||||||
|
|
||||||
def from_db_value(self, value, connection, context):
|
def from_db_value(self, value, expression, connection, context):
|
||||||
if value is not None:
|
if value is not None:
|
||||||
value = Area(**{self.area_att: value})
|
value = Area(**{self.area_att: value})
|
||||||
return value
|
return value
|
||||||
|
@ -37,7 +37,7 @@ class DistanceField(BaseField):
|
||||||
def __init__(self, distance_att):
|
def __init__(self, distance_att):
|
||||||
self.distance_att = distance_att
|
self.distance_att = distance_att
|
||||||
|
|
||||||
def from_db_value(self, value, connection, context):
|
def from_db_value(self, value, expression, connection, context):
|
||||||
if value is not None:
|
if value is not None:
|
||||||
value = Distance(**{self.distance_att: value})
|
value = Distance(**{self.distance_att: value})
|
||||||
return value
|
return value
|
||||||
|
@ -54,7 +54,7 @@ class GeomField(GeoSelectFormatMixin, BaseField):
|
||||||
# Hacky marker for get_db_converters()
|
# Hacky marker for get_db_converters()
|
||||||
geom_type = None
|
geom_type = None
|
||||||
|
|
||||||
def from_db_value(self, value, connection, context):
|
def from_db_value(self, value, expression, connection, context):
|
||||||
if value is not None:
|
if value is not None:
|
||||||
value = Geometry(value)
|
value = Geometry(value)
|
||||||
return value
|
return value
|
||||||
|
@ -71,5 +71,5 @@ class GMLField(BaseField):
|
||||||
def get_internal_type(self):
|
def get_internal_type(self):
|
||||||
return 'GMLField'
|
return 'GMLField'
|
||||||
|
|
||||||
def from_db_value(self, value, connection, context):
|
def from_db_value(self, value, expression, connection, context):
|
||||||
return value
|
return value
|
||||||
|
|
|
@ -512,7 +512,7 @@ class BaseDatabaseOperations(object):
|
||||||
"""
|
"""
|
||||||
return []
|
return []
|
||||||
|
|
||||||
def convert_durationfield_value(self, value, expression, context):
|
def convert_durationfield_value(self, value, expression, connection, context):
|
||||||
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)
|
||||||
|
|
|
@ -184,17 +184,17 @@ class DatabaseOperations(BaseDatabaseOperations):
|
||||||
converters.append(self.convert_textfield_value)
|
converters.append(self.convert_textfield_value)
|
||||||
return converters
|
return converters
|
||||||
|
|
||||||
def convert_booleanfield_value(self, value, expression, context):
|
def convert_booleanfield_value(self, value, expression, connection, context):
|
||||||
if value in (0, 1):
|
if value in (0, 1):
|
||||||
value = bool(value)
|
value = bool(value)
|
||||||
return value
|
return value
|
||||||
|
|
||||||
def convert_uuidfield_value(self, value, expression, context):
|
def convert_uuidfield_value(self, value, expression, connection, context):
|
||||||
if value is not None:
|
if value is not None:
|
||||||
value = uuid.UUID(value)
|
value = uuid.UUID(value)
|
||||||
return value
|
return value
|
||||||
|
|
||||||
def convert_textfield_value(self, value, expression, context):
|
def convert_textfield_value(self, value, expression, connection, context):
|
||||||
if value is not None:
|
if value is not None:
|
||||||
value = force_text(value)
|
value = force_text(value)
|
||||||
return value
|
return value
|
||||||
|
|
|
@ -172,7 +172,7 @@ WHEN (new.%(col_name)s IS NULL)
|
||||||
converters.append(self.convert_empty_values)
|
converters.append(self.convert_empty_values)
|
||||||
return converters
|
return converters
|
||||||
|
|
||||||
def convert_empty_values(self, value, expression, context):
|
def convert_empty_values(self, value, expression, connection, context):
|
||||||
# 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
|
||||||
|
@ -184,17 +184,17 @@ WHEN (new.%(col_name)s IS NULL)
|
||||||
value = b''
|
value = b''
|
||||||
return value
|
return value
|
||||||
|
|
||||||
def convert_textfield_value(self, value, expression, context):
|
def convert_textfield_value(self, value, expression, connection, context):
|
||||||
if isinstance(value, Database.LOB):
|
if isinstance(value, Database.LOB):
|
||||||
value = force_text(value.read())
|
value = force_text(value.read())
|
||||||
return value
|
return value
|
||||||
|
|
||||||
def convert_binaryfield_value(self, value, expression, context):
|
def convert_binaryfield_value(self, value, expression, connection, context):
|
||||||
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, context):
|
def convert_booleanfield_value(self, value, expression, connection, context):
|
||||||
if value in (1, 0):
|
if value in (1, 0):
|
||||||
value = bool(value)
|
value = bool(value)
|
||||||
return value
|
return value
|
||||||
|
@ -202,16 +202,16 @@ WHEN (new.%(col_name)s IS NULL)
|
||||||
# cx_Oracle always returns datetime.datetime objects for
|
# cx_Oracle always returns datetime.datetime objects for
|
||||||
# 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_datefield_value(self, value, expression, context):
|
def convert_datefield_value(self, value, expression, connection, context):
|
||||||
if isinstance(value, Database.Timestamp):
|
if isinstance(value, Database.Timestamp):
|
||||||
return value.date()
|
return value.date()
|
||||||
|
|
||||||
def convert_timefield_value(self, value, expression, context):
|
def convert_timefield_value(self, value, expression, connection, context):
|
||||||
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, context):
|
def convert_uuidfield_value(self, value, expression, connection, context):
|
||||||
if value is not None:
|
if value is not None:
|
||||||
value = uuid.UUID(value)
|
value = uuid.UUID(value)
|
||||||
return value
|
return value
|
||||||
|
|
|
@ -153,25 +153,25 @@ class DatabaseOperations(BaseDatabaseOperations):
|
||||||
converters.append(self.convert_uuidfield_value)
|
converters.append(self.convert_uuidfield_value)
|
||||||
return converters
|
return converters
|
||||||
|
|
||||||
def convert_decimalfield_value(self, value, expression, context):
|
def convert_decimalfield_value(self, value, expression, connection, context):
|
||||||
return backend_utils.typecast_decimal(expression.output_field.format_number(value))
|
return backend_utils.typecast_decimal(expression.output_field.format_number(value))
|
||||||
|
|
||||||
def convert_datefield_value(self, value, expression, context):
|
def convert_datefield_value(self, value, expression, connection, context):
|
||||||
if value is not None and not isinstance(value, datetime.date):
|
if value is not None and not isinstance(value, datetime.date):
|
||||||
value = parse_date(value)
|
value = parse_date(value)
|
||||||
return value
|
return value
|
||||||
|
|
||||||
def convert_datetimefield_value(self, value, expression, context):
|
def convert_datetimefield_value(self, value, expression, connection, context):
|
||||||
if value is not None and not isinstance(value, datetime.datetime):
|
if value is not None and not isinstance(value, datetime.datetime):
|
||||||
value = parse_datetime_with_timezone_support(value)
|
value = parse_datetime_with_timezone_support(value)
|
||||||
return value
|
return value
|
||||||
|
|
||||||
def convert_timefield_value(self, value, expression, context):
|
def convert_timefield_value(self, value, expression, connection, context):
|
||||||
if value is not None and not isinstance(value, datetime.time):
|
if value is not None and not isinstance(value, datetime.time):
|
||||||
value = parse_time(value)
|
value = parse_time(value)
|
||||||
return value
|
return value
|
||||||
|
|
||||||
def convert_uuidfield_value(self, value, expression, context):
|
def convert_uuidfield_value(self, value, expression, connection, context):
|
||||||
if value is not None:
|
if value is not None:
|
||||||
value = uuid.UUID(value)
|
value = uuid.UUID(value)
|
||||||
return value
|
return value
|
||||||
|
|
|
@ -77,7 +77,7 @@ class Avg(Aggregate):
|
||||||
def __init__(self, expression, **extra):
|
def __init__(self, expression, **extra):
|
||||||
super(Avg, self).__init__(expression, output_field=FloatField(), **extra)
|
super(Avg, self).__init__(expression, output_field=FloatField(), **extra)
|
||||||
|
|
||||||
def convert_value(self, value, connection, context):
|
def convert_value(self, value, expression, connection, context):
|
||||||
if value is None:
|
if value is None:
|
||||||
return value
|
return value
|
||||||
return float(value)
|
return float(value)
|
||||||
|
@ -101,7 +101,7 @@ class Count(Aggregate):
|
||||||
'False' if self.extra['distinct'] == '' else 'True',
|
'False' if self.extra['distinct'] == '' else 'True',
|
||||||
)
|
)
|
||||||
|
|
||||||
def convert_value(self, value, connection, context):
|
def convert_value(self, value, expression, connection, context):
|
||||||
if value is None:
|
if value is None:
|
||||||
return 0
|
return 0
|
||||||
return int(value)
|
return int(value)
|
||||||
|
@ -131,7 +131,7 @@ class StdDev(Aggregate):
|
||||||
'False' if self.function == 'STDDEV_POP' else 'True',
|
'False' if self.function == 'STDDEV_POP' else 'True',
|
||||||
)
|
)
|
||||||
|
|
||||||
def convert_value(self, value, connection, context):
|
def convert_value(self, value, expression, connection, context):
|
||||||
if value is None:
|
if value is None:
|
||||||
return value
|
return value
|
||||||
return float(value)
|
return float(value)
|
||||||
|
@ -156,7 +156,7 @@ class Variance(Aggregate):
|
||||||
'False' if self.function == 'VAR_POP' else 'True',
|
'False' if self.function == 'VAR_POP' else 'True',
|
||||||
)
|
)
|
||||||
|
|
||||||
def convert_value(self, value, connection, context):
|
def convert_value(self, value, expression, connection, context):
|
||||||
if value is None:
|
if value is None:
|
||||||
return value
|
return value
|
||||||
return float(value)
|
return float(value)
|
||||||
|
|
|
@ -252,7 +252,7 @@ class BaseExpression(object):
|
||||||
raise FieldError(
|
raise FieldError(
|
||||||
"Expression contains mixed types. You must set output_field")
|
"Expression contains mixed types. You must set output_field")
|
||||||
|
|
||||||
def convert_value(self, value, connection, context):
|
def convert_value(self, value, expression, connection, context):
|
||||||
"""
|
"""
|
||||||
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
|
||||||
|
@ -804,7 +804,7 @@ class Date(ExpressionNode):
|
||||||
copy.lookup_type = self.lookup_type
|
copy.lookup_type = self.lookup_type
|
||||||
return copy
|
return copy
|
||||||
|
|
||||||
def convert_value(self, value, connection, context):
|
def convert_value(self, value, expression, connection, context):
|
||||||
if isinstance(value, datetime.datetime):
|
if isinstance(value, datetime.datetime):
|
||||||
value = value.date()
|
value = value.date()
|
||||||
return value
|
return value
|
||||||
|
@ -856,7 +856,7 @@ class DateTime(ExpressionNode):
|
||||||
copy.tzname = self.tzname
|
copy.tzname = self.tzname
|
||||||
return copy
|
return copy
|
||||||
|
|
||||||
def convert_value(self, value, connection, context):
|
def convert_value(self, value, expression, connection, context):
|
||||||
if settings.USE_TZ:
|
if settings.USE_TZ:
|
||||||
if value is None:
|
if value is None:
|
||||||
raise ValueError(
|
raise ValueError(
|
||||||
|
|
|
@ -2064,7 +2064,7 @@ class ForeignKey(ForeignObject):
|
||||||
def db_parameters(self, connection):
|
def db_parameters(self, connection):
|
||||||
return {"type": self.db_type(connection), "check": []}
|
return {"type": self.db_type(connection), "check": []}
|
||||||
|
|
||||||
def convert_empty_strings(self, value, connection, context):
|
def convert_empty_strings(self, value, expression, connection, context):
|
||||||
if (not value) and isinstance(value, six.string_types):
|
if (not value) and isinstance(value, six.string_types):
|
||||||
return None
|
return None
|
||||||
return value
|
return value
|
||||||
|
|
|
@ -760,17 +760,15 @@ class SQLCompiler(object):
|
||||||
backend_converters = self.connection.ops.get_db_converters(expression)
|
backend_converters = self.connection.ops.get_db_converters(expression)
|
||||||
field_converters = expression.get_db_converters(self.connection)
|
field_converters = expression.get_db_converters(self.connection)
|
||||||
if backend_converters or field_converters:
|
if backend_converters or field_converters:
|
||||||
converters[i] = (backend_converters, field_converters, expression)
|
converters[i] = (backend_converters + field_converters, expression)
|
||||||
return converters
|
return converters
|
||||||
|
|
||||||
def apply_converters(self, row, converters):
|
def apply_converters(self, row, converters):
|
||||||
row = list(row)
|
row = list(row)
|
||||||
for pos, (backend_converters, field_converters, field) in converters.items():
|
for pos, (convs, expression) in converters.items():
|
||||||
value = row[pos]
|
value = row[pos]
|
||||||
for converter in backend_converters:
|
for converter in convs:
|
||||||
value = converter(value, field, self.query.context)
|
value = converter(value, expression, self.connection, self.query.context)
|
||||||
for converter in field_converters:
|
|
||||||
value = converter(value, self.connection, self.query.context)
|
|
||||||
row[pos] = value
|
row[pos] = value
|
||||||
return tuple(row)
|
return tuple(row)
|
||||||
|
|
||||||
|
|
|
@ -477,7 +477,7 @@ instances::
|
||||||
class HandField(models.Field):
|
class HandField(models.Field):
|
||||||
# ...
|
# ...
|
||||||
|
|
||||||
def from_db_value(self, value, connection, context):
|
def from_db_value(self, value, expression, connection, context):
|
||||||
if value is None:
|
if value is None:
|
||||||
return value
|
return value
|
||||||
return parse_hand(value)
|
return parse_hand(value)
|
||||||
|
|
|
@ -412,7 +412,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(self, value, connection, context)
|
.. method:: convert_value(self, value, expression, connection, context)
|
||||||
|
|
||||||
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.
|
||||||
|
|
|
@ -1630,7 +1630,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, connection, context)
|
.. method:: from_db_value(value, expression, connection, context)
|
||||||
|
|
||||||
.. versionadded:: 1.8
|
.. versionadded:: 1.8
|
||||||
|
|
||||||
|
|
|
@ -43,7 +43,7 @@ class MyAutoField(models.CharField):
|
||||||
value = MyWrapper(value)
|
value = MyWrapper(value)
|
||||||
return value
|
return value
|
||||||
|
|
||||||
def from_db_value(self, value, connection, context):
|
def from_db_value(self, value, expression, connection, context):
|
||||||
if not value:
|
if not value:
|
||||||
return
|
return
|
||||||
return MyWrapper(value)
|
return MyWrapper(value)
|
||||||
|
|
|
@ -18,7 +18,7 @@ class CashField(models.DecimalField):
|
||||||
kwargs['decimal_places'] = 2
|
kwargs['decimal_places'] = 2
|
||||||
super(CashField, self).__init__(**kwargs)
|
super(CashField, self).__init__(**kwargs)
|
||||||
|
|
||||||
def from_db_value(self, value, connection, context):
|
def from_db_value(self, value, expression, connection, context):
|
||||||
cash = Cash(value)
|
cash = Cash(value)
|
||||||
cash.vendor = connection.vendor
|
cash.vendor = connection.vendor
|
||||||
return cash
|
return cash
|
||||||
|
|
|
@ -112,7 +112,7 @@ class TeamField(models.CharField):
|
||||||
return value
|
return value
|
||||||
return Team(value)
|
return Team(value)
|
||||||
|
|
||||||
def from_db_value(self, value, connection, context):
|
def from_db_value(self, value, expression, connection, context):
|
||||||
return Team(value)
|
return Team(value)
|
||||||
|
|
||||||
def value_to_string(self, obj):
|
def value_to_string(self, obj):
|
||||||
|
|
Loading…
Reference in New Issue