Sfoglia il codice sorgente

Refs #28459 -- Improved performance of BaseExpression.convert_value().

Sergey Fedoseev 7 anni fa
parent
commit
47ccefeada
1 ha cambiato i file con 22 aggiunte e 9 eliminazioni
  1. 22 9
      django/db/models/expressions.py

+ 22 - 9
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)