Колонка миграции Django не существует Ошибка ProgrammingError при выполнении тестов
Я столкнулся с ошибкой при тестировании приложения django с помощью pytest, а точнее при запуске тестов, если я выполнил миграцию, которая удаляет поле, использованное в более ранней миграции. Если сделать это вне тестов, то ошибка не возникает.
Для размножения:
models.py
from django.db import models
class TestModel(models.Model):
# We started with this field, but now longer need it
# original_text = models.CharField(max_length=255)
# We added this field and then moved over to it
new_text = models.CharField(max_length=511)
migrations/0001_initial.py
from django.db import migrations, models
class Migration(migrations.Migration):
initial = True
dependencies = [
]
operations = [
migrations.CreateModel(
name='TestModel',
fields=[
('id', models.BigAutoField(auto_created=True, primary_key=True, serialize=False, verbose_name='ID')),
('original_text', models.CharField(max_length=255)),
],
),
]
migrations/0002_testmodel_new_text.py
from django.db import migrations, models
def move_text_to_other_field_and_append_new(apps, schema_editor):
TestModel = apps.get_model("sample", "TestModel")
for test_model in TestModel.objects.all():
test_model.new_text = test_model.original_text + " new"
test_model.save()
class Migration(migrations.Migration):
dependencies = [
('sample', '0001_initial'),
]
operations = [
migrations.AddField(
model_name='testmodel',
name='new_text',
field=models.CharField(default='', max_length=511),
preserve_default=False,
),
migrations.RunPython(move_text_to_other_field_and_append_new, migrations.RunPython.noop)
]
migrations/0003_remove_testmodel_original_text.py
from django.db import migrations
class Migration(migrations.Migration):
dependencies = [
('sample', '0002_testmodel_new_text'),
]
operations = [
migrations.RemoveField(
model_name='testmodel',
name='original_text',
),
]
tests.py
from django.test import TestCase
class TestModelTestCase(TestCase):
def test_example(self):
self.assertEqual(1, 1)
Это минимальная настройка для воспроизведения ошибки. Теперь при выполнении pipenv run pytest sample/tests.py
я получаю ошибку ERROR sample/tests.py::TestModelTestCase::test_example - django.db.utils.ProgrammingError: column sample_testmodel.original_text does not exist
. В стеке ошибок четко указано следующее:
sample/migrations/0002_testmodel_new_text.py:9: in move_text_to_other_field_and_append_new
for test_model in TestModel.objects.all():
И затем:
self = <django.db.backends.utils.CursorWrapper object at 0x7f3e53a40e80>, sql = 'SELECT "sample_testmodel"."id", "sample_testmodel"."original_text", "sample_testmodel"."new_text" FROM "sample_testmodel"', params = ()
ignored_wrapper_args = (False, {'connection': <django.db.backends.postgresql.base.DatabaseWrapper object at 0x7f3e5d7e5d90>, 'cursor': <django.db.backends.utils.CursorWrapper object at 0x7f3e53a40e80>})
def _execute(self, sql, params, *ignored_wrapper_args):
self.db.validate_no_broken_transaction()
with self.db.wrap_database_errors:
if params is None:
# params default might be backend specific.
return self.cursor.execute(sql)
else:
> return self.cursor.execute(sql, params)
E django.db.utils.ProgrammingError: column sample_testmodel.original_text does not exist
E LINE 1: SELECT "sample_testmodel"."id", "sample_testmodel"."original...
E ^
../../../.local/share/virtualenvs/sprancher-wR5ufyMh/lib/python3.8/site-packages/django/db/backends/utils.py:84: ProgrammingError
Это беспокоит меня уже долгое время. Это происходит только в тестах. Комментирование строки RunPython
в 0002 помогло, но это явно не долгосрочное решение. Запуск тестов перед добавлением 0003 выдает зеленый свет, до этого момента проблем не было. Порядок выполнения кажется мне неправильным или что-то в этом роде, но я никак не могу понять, в чем дело.
Мой вопрос в том, почему это происходит и как я могу предотвратить это?