Refs -- Improved performance of BaseExpression.convert_value().
@@ -144,8 +144,18 @@ class BaseExpression:
if output_field is not None:
self.output_field = output_field
+ def __getstate__(self):
+ # This method required only for Python 3.4.
+ state = self.__dict__.copy()
+ state.pop('convert_value', None)
+ return state
+
def get_db_converters(self, connection):
- return [self.convert_value] + self.output_field.get_db_converters(connection)
+ return (
+ []
+ if self.convert_value is self._convert_value_noop else
+ [self.convert_value]
+ ) + self.output_field.get_db_converters(connection)
def get_source_expressions(self):
return []
@@ -274,7 +284,12 @@ class BaseExpression:
raise FieldError('Expression contains mixed types. You must set output_field.')
return output_field
- def convert_value(self, value, expression, connection):
+ @staticmethod
+ def _convert_value_noop(value, expression, connection):
+ return value
+
+ @cached_property
+ def convert_value(self):
"""
Expressions provide their own converters because users have the option
of manually specifying the output_field which may be a different type
@@ -282,15 +297,13 @@ class BaseExpression:
"""
field = self.output_field
internal_type = field.get_internal_type()
- if value is None:
- return value
- elif internal_type == 'FloatField':
- return float(value)
+ if internal_type == 'FloatField':
+ return lambda value, expression, connection: None if value is None else float(value)
elif internal_type.endswith('IntegerField'):
- return int(value)
+ return lambda value, expression, connection: None if value is None else int(value)
elif internal_type == 'DecimalField':
- return Decimal(value)
- return value
+ return lambda value, expression, connection: None if value is None else Decimal(value)
+ return self._convert_value_noop
def get_lookup(self, lookup):
return self.output_field.get_lookup(lookup)
