summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorSergey Fedoseev <fedoseev.sergey@gmail.com>2017-08-12 03:34:50 +0500
committerTim Graham <timograham@gmail.com>2017-08-11 18:34:50 -0400
commit47ccefeada926ffbccaa354dec7a987a7e7ca701 (patch)
tree58d968933492453740846301c3ef5ff5b0139c37
parentd04b324969e045d1cf2bf7da18ea0497d8066935 (diff)
Refs #28459 -- Improved performance of BaseExpression.convert_value().
-rw-r--r--django/db/models/expressions.py31
1 files changed, 22 insertions, 9 deletions
diff --git a/django/db/models/expressions.py b/django/db/models/expressions.py
index b9d03111c8..ff7921b520 100644
--- a/django/db/models/expressions.py
+++ b/django/db/models/expressions.py
@@ -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)