Django alterfield migration to textfield fails [duplicate]

Миграция для пакета Django django-mail-queue содержит следующее в соответствующей части:

migrations.AlterField(
            model_name='mailermessage',
            name='to_address',
            field=models.TextField(db_index=True, verbose_name='To'),
        ),

Но на MySQL 9.0.1 (Django 5.1.5) это не удается со следующей ошибкой:

django.db.utils.OperationalError: (1170, "BLOB/TEXT column 'to_address' 
used in key specification without a key length")

Есть идеи, почему? Я нашел закрытый отчет об ошибке для Django (несколько лет назад), в котором были проблемы с подобным запросом AlterField, но, похоже, это не связано.

Поле было создано в миграции 0001 следующим образом:

        migrations.CreateModel(
            name='MailerMessage',
            fields=[
                ('id', models.AutoField(verbose_name='ID', serialize=False,
                                        auto_created=True, primary_key=True)),
                ('subject', models.CharField(max_length=250, verbose_name='Subject', blank=True)),
                ('to_address', models.TextField(verbose_name='To')),
                ('bcc_address', models.TextField(verbose_name='BCC', blank=True)),
                ('from_address', models.EmailField(max_length=250, verbose_name='From')),
                ('content', models.TextField(verbose_name='Content', blank=True)),
                ('html_content', models.TextField(verbose_name='HTML Content', blank=True)),
                ('app', models.CharField(max_length=250, verbose_name='App', blank=True)),
                ('sent', models.BooleanField(default=False, verbose_name='Sent', editable=False)),
                ('last_attempt', models.DateTimeField(verbose_name='Last attempt',
                                                      null=True, editable=False, blank=True)),
            ],
            options={
                'verbose_name': 'Message',
                'verbose_name_plural': 'Messages',
            },
            bases=(models.Model,),
        ),

В списке миграций нет других ссылок на это поле.

Предложенная ниже команда sqlmigrate выдала следующий результат:

--
-- Alter field file_attachment on attachment
--
-- (no-op)
--
-- Alter field sent on mailermessage
--
CREATE INDEX `mailqueue_mailermessage_sent_5a2c49dd` ON `mailqueue_mailermessage` (`sent`);
--
-- Alter field to_address on mailermessage
--
CREATE INDEX `mailqueue_mailermessage_to_address_88fb3d2d` ON `mailqueue_mailermessage` (`to_address`);

Но я не знаю, решена ли проблема или она повторится в производстве.

Причина, по которой это происходит, заключается в том, что Django стремится быть независимым от диалекта SQL, но некоторые технические детали, касающиеся различных баз данных, пока не освещены.

В данном конкретном случае может ли база данных MySQL не индексировать поле VARCHAR(…), если максимальная длина довольно велика, или для TEXT, где вообще нет ограничений. MySQL может добавить индекс для элементов, содержащих не более 255 символов.

The migration thus aims to add an index on the to_address field, and that field can not be indexed in MySQL. The index is however strictly speaking not necessary to get the thing working. We can fake the migration [Django-doc], so that Django thinks we did the migration, whereas in reality, we did not. We can do this by first migrating up to 0007, then fake 0008, and finally run the rest of the migrations, like:

python3 manage.py migrate mailqueue 0007
python3 manage.py migrate --fake mailqueue 0008
python3 manage.py migrate mailqueue
Вернуться на верх