mirror of
				https://github.com/django/django.git
				synced 2025-10-31 01:25:32 +00:00 
			
		
		
		
	[1.7.x] Fixed #22581: Pass default values for schema through get_db_prep_save()
This commit is contained in:
		| @@ -167,6 +167,9 @@ class BaseDatabaseSchemaEditor(object): | |||||||
|         # If it's a callable, call it |         # If it's a callable, call it | ||||||
|         if callable(default): |         if callable(default): | ||||||
|             default = default() |             default = default() | ||||||
|  |         # Run it through the field's get_db_prep_save method so we can send it | ||||||
|  |         # to the database. | ||||||
|  |         default = field.get_db_prep_save(default, self.connection) | ||||||
|         return default |         return default | ||||||
|  |  | ||||||
|     def quote_value(self, value): |     def quote_value(self, value): | ||||||
|   | |||||||
| @@ -1,3 +1,4 @@ | |||||||
|  | from decimal import Decimal | ||||||
| from django.utils import six | from django.utils import six | ||||||
| from django.apps.registry import Apps | from django.apps.registry import Apps | ||||||
| from django.db.backends.schema import BaseDatabaseSchemaEditor | from django.db.backends.schema import BaseDatabaseSchemaEditor | ||||||
| @@ -19,6 +20,8 @@ class DatabaseSchemaEditor(BaseDatabaseSchemaEditor): | |||||||
|         # Manual emulation of SQLite parameter quoting |         # Manual emulation of SQLite parameter quoting | ||||||
|         if isinstance(value, type(True)): |         if isinstance(value, type(True)): | ||||||
|             return str(int(value)) |             return str(int(value)) | ||||||
|  |         elif isinstance(value, (Decimal, float)): | ||||||
|  |             return str(value) | ||||||
|         elif isinstance(value, six.integer_types): |         elif isinstance(value, six.integer_types): | ||||||
|             return str(value) |             return str(value) | ||||||
|         elif isinstance(value, six.string_types): |         elif isinstance(value, six.string_types): | ||||||
| @@ -26,7 +29,7 @@ class DatabaseSchemaEditor(BaseDatabaseSchemaEditor): | |||||||
|         elif value is None: |         elif value is None: | ||||||
|             return "NULL" |             return "NULL" | ||||||
|         else: |         else: | ||||||
|             raise ValueError("Cannot quote parameter value %r" % value) |             raise ValueError("Cannot quote parameter value %r of type %s" % (value, type(value))) | ||||||
|  |  | ||||||
|     def _remake_table(self, model, create_fields=[], delete_fields=[], alter_fields=[], rename_fields=[], override_uniques=None): |     def _remake_table(self, model, create_fields=[], delete_fields=[], alter_fields=[], rename_fields=[], override_uniques=None): | ||||||
|         """ |         """ | ||||||
| @@ -52,7 +55,7 @@ class DatabaseSchemaEditor(BaseDatabaseSchemaEditor): | |||||||
|             # If there's a default, insert it into the copy map |             # If there's a default, insert it into the copy map | ||||||
|             if field.has_default(): |             if field.has_default(): | ||||||
|                 mapping[field.column] = self.quote_value( |                 mapping[field.column] = self.quote_value( | ||||||
|                     field.get_default() |                     self.effective_default(field) | ||||||
|                 ) |                 ) | ||||||
|         # Add in any altered fields |         # Add in any altered fields | ||||||
|         for (old_field, new_field) in alter_fields: |         for (old_field, new_field) in alter_fields: | ||||||
|   | |||||||
| @@ -231,6 +231,40 @@ class SchemaTests(TransactionTestCase): | |||||||
|         else: |         else: | ||||||
|             self.assertEqual(field_type, 'BooleanField') |             self.assertEqual(field_type, 'BooleanField') | ||||||
|  |  | ||||||
|  |     def test_add_field_default_transform(self): | ||||||
|  |         """ | ||||||
|  |         Tests adding fields to models with a default that is not directly | ||||||
|  |         valid in the database (#22581) | ||||||
|  |         """ | ||||||
|  |         class TestTransformField(IntegerField): | ||||||
|  |             # Weird field that saves the count of items in its value | ||||||
|  |             def get_default(self): | ||||||
|  |                 return self.default | ||||||
|  |             def get_prep_value(self, value): | ||||||
|  |                 if value is None: | ||||||
|  |                     return 0 | ||||||
|  |                 return len(value) | ||||||
|  |         # Create the table | ||||||
|  |         with connection.schema_editor() as editor: | ||||||
|  |             editor.create_model(Author) | ||||||
|  |         # Add some rows of data | ||||||
|  |         Author.objects.create(name="Andrew", height=30) | ||||||
|  |         Author.objects.create(name="Andrea") | ||||||
|  |         # Add the field with a default it needs to cast (to string in this case) | ||||||
|  |         new_field = TestTransformField(default={1:2}) | ||||||
|  |         new_field.set_attributes_from_name("thing") | ||||||
|  |         with connection.schema_editor() as editor: | ||||||
|  |             editor.add_field( | ||||||
|  |                 Author, | ||||||
|  |                 new_field, | ||||||
|  |             ) | ||||||
|  |         # Ensure the field is there | ||||||
|  |         columns = self.column_classes(Author) | ||||||
|  |         field_type, field_info = columns['thing'] | ||||||
|  |         self.assertEqual(field_type, 'IntegerField') | ||||||
|  |         # Make sure the values were transformed correctly | ||||||
|  |         self.assertEqual(Author.objects.extra(where=["thing = 1"]).count(), 2) | ||||||
|  |  | ||||||
|     def test_alter(self): |     def test_alter(self): | ||||||
|         """ |         """ | ||||||
|         Tests simple altering of fields |         Tests simple altering of fields | ||||||
|   | |||||||
		Reference in New Issue
	
	Block a user