diff --git a/AUTHORS b/AUTHORS index dfaa1038f1..8a49df0472 100644 --- a/AUTHORS +++ b/AUTHORS @@ -8,6 +8,7 @@ answer newbie questions, and generally made Django that much better: Aaron Cannon Aaron Swartz Aaron T. Myers + Adam Johnson Adam Vandenberg Adrian Holovaty Adrien Lemaire diff --git a/django/db/backends/mysql/schema.py b/django/db/backends/mysql/schema.py index ca650ac1af..d36726b134 100644 --- a/django/db/backends/mysql/schema.py +++ b/django/db/backends/mysql/schema.py @@ -34,10 +34,17 @@ class DatabaseSchemaEditor(BaseDatabaseSchemaEditor): def skip_default(self, field): """ - MySQL doesn't accept default values for longtext and longblob - and implicitly treats these columns as nullable. + MySQL doesn't accept default values for TEXT and BLOB types, and + implicitly treats these columns as nullable. """ - return field.db_type(self.connection) in {'longtext', 'longblob'} + db_type = field.db_type(self.connection) + return ( + db_type is not None and + db_type.lower() in { + 'tinyblob', 'blob', 'mediumblob', 'longblob', + 'tinytext', 'text', 'mediumtext', 'longtext', + } + ) def add_field(self, model, field): super(DatabaseSchemaEditor, self).add_field(model, field) diff --git a/tests/schema/fields.py b/tests/schema/fields.py index 0392a29aa2..8499477d65 100644 --- a/tests/schema/fields.py +++ b/tests/schema/fields.py @@ -1,3 +1,4 @@ +from django.db import models from django.db.models.fields.related import ( RECURSIVE_RELATIONSHIP_CONSTANT, ManyRelatedObjectsDescriptor, ManyToManyField, ManyToManyRel, RelatedField, @@ -56,3 +57,11 @@ class CustomManyToManyField(RelatedField): class InheritedManyToManyField(ManyToManyField): pass + + +class MediumBlobField(models.BinaryField): + """ + A MySQL BinaryField that uses a different blob size. + """ + def db_type(self, connection): + return 'MEDIUMBLOB' diff --git a/tests/schema/tests.py b/tests/schema/tests.py index 5128c9ec1e..2c4e79f98d 100644 --- a/tests/schema/tests.py +++ b/tests/schema/tests.py @@ -17,7 +17,9 @@ from django.db.models.fields.related import ( from django.db.transaction import atomic from django.test import TransactionTestCase, skipIfDBFeature -from .fields import CustomManyToManyField, InheritedManyToManyField +from .fields import ( + CustomManyToManyField, InheritedManyToManyField, MediumBlobField, +) from .models import ( Author, AuthorWithDefaultHeight, AuthorWithEvenLongerName, Book, BookWeak, BookWithLongName, BookWithO2O, BookWithSlug, Note, NoteRename, Tag, @@ -383,6 +385,23 @@ class SchemaTests(TransactionTestCase): # these two types. self.assertIn(columns['bits'][0], ("BinaryField", "TextField")) + @unittest.skipUnless(connection.vendor == 'mysql', "MySQL specific") + def test_add_binaryfield_mediumblob(self): + """ + Test adding a custom-sized binary field on MySQL (#24846). + """ + # Create the table + with connection.schema_editor() as editor: + editor.create_model(Author) + # Add the new field with default + new_field = MediumBlobField(blank=True, default=b'123') + new_field.set_attributes_from_name('bits') + with connection.schema_editor() as editor: + editor.add_field(Author, new_field) + columns = self.column_classes(Author) + # Introspection treats BLOBs as TextFields + self.assertEqual(columns['bits'][0], "TextField") + def test_alter(self): """ Tests simple altering of fields