#32503: AlterField migration to TextField with default fails on MySQL 8.0.13+
-----------------------------------------+------------------------
Reporter: Matt Westcott | Owner: nobody
Type: Bug | Status: new
Component: Migrations | Version: 3.0
Severity: Normal | Keywords:
Triage Stage: Unreviewed | Has patch: 0
Needs documentation: 0 | Needs tests: 0
Patch needs improvement: 0 | Easy pickings: 0
UI/UX: 0 |
-----------------------------------------+------------------------
On MySQL 8.0.23 with mysqlclient==2.0.3, running a migration with an
AlterField operation that changes a field to a TextField with a default
value fails with the error: `MySQLdb._exceptions.OperationalError: (1101,
"BLOB, TEXT, GEOMETRY or JSON column 'body' can't have a default value")`.
To reproduce:
On a fresh project configured with a MySQL 8.0.23 database, add a `base`
app with the following definition in models.py:
{{{
from django.db import models
class Article(models.Model):
body = models.CharField(max_length=255, null=True, blank=True)
}}}
Run `./manage.py makemigrations`
Edit models.py to
{{{
from django.db import models
class Article(models.Model):
body = models.TextField(blank=True)
}}}
and re-run `./manage.py makemigrations`, entering `""` as the default when
prompted. This should generate the migration:
{{{
from django.db import migrations, models
class Migration(migrations.Migration):
dependencies = [
('base', '0001_initial'),
]
operations = [
migrations.AlterField(
model_name='article',
name='body',
field=models.TextField(blank=True, default=''),
preserve_default=False,
),
]
}}}
`./manage.py migrate` then fails with the output:
{{{
System check identified some issues:
WARNINGS:
base.Article: (models.W042) Auto-created primary key used when not
defining a primary key type, by default 'django.db.models.AutoField'.
HINT: Configure the DEFAULT_AUTO_FIELD setting or the
BaseConfig.default_auto_field attribute to point to a subclass of
AutoField, e.g. 'django.db.models.BigAutoField'.
Operations to perform:
Apply all migrations: admin, auth, base, contenttypes, sessions
Running migrations:
Applying base.0001_initial... OK
Applying base.0002_auto_20210303_1601...Traceback (most recent call
last):
File "/vagrant/libs/django/django/db/backends/utils.py", line 84, in
_execute
return self.cursor.execute(sql, params)
File "/vagrant/libs/django/django/db/backends/mysql/base.py", line 73,
in execute
return self.cursor.execute(query, args)
File "/home/vagrant/.virtualenvs/wagtailmysql/lib/python3.6/site-
packages/MySQLdb/cursors.py", line 206, in execute
res = self._query(query)
File "/home/vagrant/.virtualenvs/wagtailmysql/lib/python3.6/site-
packages/MySQLdb/cursors.py", line 319, in _query
db.query(q)
File "/home/vagrant/.virtualenvs/wagtailmysql/lib/python3.6/site-
packages/MySQLdb/connections.py", line 259, in query
_mysql.connection.query(self, query)
MySQLdb._exceptions.OperationalError: (1101, "BLOB, TEXT, GEOMETRY or JSON
column 'body' can't have a default value")
The above exception was the direct cause of the following exception:
Traceback (most recent call last):
File "./manage.py", line 21, in <module>
main()
File "./manage.py", line 17, in main
execute_from_command_line(sys.argv)
File "/vagrant/libs/django/django/core/management/__init__.py", line
419, in execute_from_command_line
utility.execute()
File "/vagrant/libs/django/django/core/management/__init__.py", line
413, in execute
self.fetch_command(subcommand).run_from_argv(self.argv)
File "/vagrant/libs/django/django/core/management/base.py", line 354, in
run_from_argv
self.execute(*args, **cmd_options)
File "/vagrant/libs/django/django/core/management/base.py", line 398, in
execute
output = self.handle(*args, **options)
File "/vagrant/libs/django/django/core/management/base.py", line 89, in
wrapped
res = handle_func(*args, **kwargs)
File "/vagrant/libs/django/django/core/management/commands/migrate.py",
line 246, in handle
fake_initial=fake_initial,
File "/vagrant/libs/django/django/db/migrations/executor.py", line 117,
in migrate
state = self._migrate_all_forwards(state, plan, full_plan, fake=fake,
fake_initial=fake_initial)
File "/vagrant/libs/django/django/db/migrations/executor.py", line 147,
in _migrate_all_forwards
state = self.apply_migration(state, migration, fake=fake,
fake_initial=fake_initial)
File "/vagrant/libs/django/django/db/migrations/executor.py", line 227,
in apply_migration
state = migration.apply(state, schema_editor)
File "/vagrant/libs/django/django/db/migrations/migration.py", line 126,
in apply
operation.database_forwards(self.app_label, schema_editor, old_state,
project_state)
File "/vagrant/libs/django/django/db/migrations/operations/fields.py",
line 244, in database_forwards
schema_editor.alter_field(from_model, from_field, to_field)
File "/vagrant/libs/django/django/db/backends/base/schema.py", line 595,
in alter_field
old_db_params, new_db_params, strict)
File "/vagrant/libs/django/django/db/backends/base/schema.py", line 756,
in _alter_field
params,
File "/vagrant/libs/django/django/db/backends/base/schema.py", line 145,
in execute
cursor.execute(sql, params)
File "/vagrant/libs/django/django/db/backends/utils.py", line 98, in
execute
return super().execute(sql, params)
File "/vagrant/libs/django/django/db/backends/utils.py", line 66, in
execute
return self._execute_with_wrappers(sql, params, many=False,
executor=self._execute)
File "/vagrant/libs/django/django/db/backends/utils.py", line 75, in
_execute_with_wrappers
return executor(sql, params, many, context)
File "/vagrant/libs/django/django/db/backends/utils.py", line 84, in
_execute
return self.cursor.execute(sql, params)
File "/vagrant/libs/django/django/db/utils.py", line 90, in __exit__
raise dj_exc_value.with_traceback(traceback) from exc_value
File "/vagrant/libs/django/django/db/backends/utils.py", line 84, in
_execute
return self.cursor.execute(sql, params)
File "/vagrant/libs/django/django/db/backends/mysql/base.py", line 73,
in execute
return self.cursor.execute(query, args)
File "/home/vagrant/.virtualenvs/wagtailmysql/lib/python3.6/site-
packages/MySQLdb/cursors.py", line 206, in execute
res = self._query(query)
File "/home/vagrant/.virtualenvs/wagtailmysql/lib/python3.6/site-
packages/MySQLdb/cursors.py", line 319, in _query
db.query(q)
File "/home/vagrant/.virtualenvs/wagtailmysql/lib/python3.6/site-
packages/MySQLdb/connections.py", line 259, in query
_mysql.connection.query(self, query)
django.db.utils.OperationalError: (1101, "BLOB, TEXT, GEOMETRY or JSON
column 'body' can't have a default value")
}}}
Bisecting shows that this error was introduced in
https://github.com/django/django/commit/6b16c91157512587017e9178d066ed1a683e7795
- presumably prior to this the default was simply being ignored on MySQL.
--
Ticket URL: <https://code.djangoproject.com/ticket/32503>
Django <https://code.djangoproject.com/>
The Web framework for perfectionists with deadlines.
--
You received this message because you are subscribed to the Google Groups
"Django updates" group.
To unsubscribe from this group and stop receiving emails from it, send an email
to [email protected].
To view this discussion on the web visit
https://groups.google.com/d/msgid/django-updates/049.ff94b3acb880f66af2ed6554d1f28dd2%40djangoproject.com.