Skip to content
This repository

HTTPS clone URL

Subversion checkout URL

You can clone with HTTPS or Subversion.

Download ZIP
Browse code

Fixed #13844 -- Avoid converting unknown db values to float

This patch removes an unconditional float(value) conversion from db
backend default convert_values() method. This can cause problems when
aggregating over character fields for example. In addition, Oracle
and SQLite already return the bare value from their convert_values().

In the long term the converting should be done by fields, and the
fields should then call database backend specific converters when
needed. The current setup is inflexible for 3rd party fields.

Thanks to Merlijn van Deen for the original patch.
  • Loading branch information...
commit fe1e4f4e3ca3a70cdc3d327f9021b349fa75b431 1 parent 3434051
Anssi Kääriäinen authored July 15, 2012
12  django/db/backends/__init__.py
@@ -856,19 +856,19 @@ def year_lookup_bounds_for_date_field(self, value):
856 856
         return self.year_lookup_bounds(value)
857 857
 
858 858
     def convert_values(self, value, field):
859  
-        """Coerce the value returned by the database backend into a consistent type that
860  
-        is compatible with the field type.
  859
+        """
  860
+        Coerce the value returned by the database backend into a consistent type
  861
+        that is compatible with the field type.
861 862
         """
862 863
         internal_type = field.get_internal_type()
863 864
         if internal_type == 'DecimalField':
864 865
             return value
865  
-        elif internal_type and internal_type.endswith('IntegerField') or internal_type == 'AutoField':
  866
+        elif (internal_type and (internal_type.endswith('IntegerField')
  867
+                                 or internal_type == 'AutoField')):
866 868
             return int(value)
867 869
         elif internal_type in ('DateField', 'DateTimeField', 'TimeField'):
868 870
             return value
869  
-        # No field, or the field isn't known to be a decimal or integer
870  
-        # Default to a float
871  
-        return float(value)
  871
+        return value
872 872
 
873 873
     def check_aggregate_support(self, aggregate_func):
874 874
         """Check that the backend supports the provided aggregate
13  tests/regressiontests/aggregation_regress/tests.py
@@ -865,3 +865,16 @@ def test_filtering_by_annotation_name(self):
865 865
             ['Peter Norvig'],
866 866
             lambda b: b.name
867 867
         )
  868
+
  869
+    def test_type_conversion_for_CharField_aggregations(self):
  870
+        # regression test for #13844
  871
+        # the database backend convert_values function should not case
  872
+        # CharFields to float.
  873
+        from django.db.models import CharField
  874
+        from django.db import connection
  875
+        testData = u'not_a_float_value'
  876
+        testField = CharField()
  877
+        self.assertEqual(
  878
+            connection.ops.convert_values(testData, testField),
  879
+            testData
  880
+        )

0 notes on commit fe1e4f4

Please sign in to comment.
Something went wrong with that request. Please try again.