﻿id	summary	reporter	owner	description	type	status	component	version	severity	resolution	keywords	cc	stage	has_patch	needs_docs	needs_tests	needs_better_patch	easy	ui_ux
32503	AlterField migration to TextField with default fails on MySQL 8.0.13+	Matt Westcott	Yuekui	"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."	Bug	closed	Migrations	3.0	Normal	fixed	mysql default	Adam Johnson Matt Westcott	Ready for checkin	1	0	0	0	0	0
