pytest-dev/pytest-django

Error when applying migrations but works in django test suite

ollejernstrom opened this issue · 4 comments

Background

I have an issue when i using pytest. Originally was using pytest-django for running my test suite but after it broke i switched to django test suite. I really like pytest and want to make it work.

Issue

The error seem to originate from running the migrations since if i delete all my migrations, remake them, and run pytest it works, but sadly that is not a possibility in my production environment. It also works when running manage.py test so the issue should not be with the migration it self.

Context

As seen in the error: Column sop_soptask.media_file does not exist and stacktrack: Perhaps you meant to reference the column "sop_soptask.media_file_id".

What this migration (series of migrations) did was extract my sop_soptask.mediafile (Django File field) into a general file model which can be rereferenced and reused (stores poster, blurhash, thumbnail et.c.). so the field has the same name.

Error

ERROR sop/tests/test_task_versions.py::SOPTaskVersionTest::test_new_version_of_task_without_content - django.db.utils.ProgrammingError: column sop_soptask.media_file does not exist

Stacktrace

venv/lib/python3.11/site-packages/pytest_django/fixtures.py:140: in django_db_setup
    db_cfg = setup_databases(
venv/lib/python3.11/site-packages/django/test/utils.py:220: in setup_databases
    connection.creation.create_test_db(
venv/lib/python3.11/site-packages/django/db/backends/base/creation.py:78: in create_test_db
    call_command(
venv/lib/python3.11/site-packages/django/core/management/__init__.py:198: in call_command
    return command.execute(*args, **defaults)
venv/lib/python3.11/site-packages/django/core/management/base.py:448: in execute
    output = self.handle(*args, **options)
venv/lib/python3.11/site-packages/django/core/management/base.py:96: in wrapped
    res = handle_func(*args, **kwargs)
venv/lib/python3.11/site-packages/django/core/management/commands/migrate.py:349: in handle
    post_migrate_state = executor.migrate(
venv/lib/python3.11/site-packages/django/db/migrations/executor.py:135: in migrate
    state = self._migrate_all_forwards(
venv/lib/python3.11/site-packages/django/db/migrations/executor.py:167: in _migrate_all_forwards
    state = self.apply_migration(
venv/lib/python3.11/site-packages/django/db/migrations/executor.py:252: in apply_migration
    state = migration.apply(state, schema_editor)
venv/lib/python3.11/site-packages/django/db/migrations/migration.py:130: in apply
    operation.database_forwards(
venv/lib/python3.11/site-packages/django/db/migrations/operations/special.py:193: in database_forwards
    self.code(from_state.apps, schema_editor)
files/migrations/0009_update_old_shared_files_and_create_new.py:244: in migrate_mediafile_file_to_file_id
    handle_task_uploaded_files(apps)
files/migrations/0009_update_old_shared_files_and_create_new.py:121: in handle_task_uploaded_files
    for task in tasks_to_handle:
venv/lib/python3.11/site-packages/django/db/models/query.py:394: in __iter__
    self._fetch_all()
venv/lib/python3.11/site-packages/django/db/models/query.py:1866: in _fetch_all
    self._result_cache = list(self._iterable_class(self))
venv/lib/python3.11/site-packages/django/db/models/query.py:87: in __iter__
    results = compiler.execute_sql(
venv/lib/python3.11/site-packages/django/db/models/sql/compiler.py:1398: in execute_sql
    cursor.execute(sql, params)
venv/lib/python3.11/site-packages/django/db/backends/utils.py:67: in execute
    return self._execute_with_wrappers(
venv/lib/python3.11/site-packages/django/db/backends/utils.py:80: in _execute_with_wrappers
    return executor(sql, params, many, context)
venv/lib/python3.11/site-packages/django/db/backends/utils.py:84: in _execute
    with self.db.wrap_database_errors:
venv/lib/python3.11/site-packages/django/db/utils.py:91: in __exit__
    raise dj_exc_value.with_traceback(traceback) from exc_value
_ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _

self = <django.db.backends.utils.CursorWrapper object at 0x139a0a610>
sql = 'SELECT "sop_soptask"."id", "sop_soptask"."order", "sop_soptask"."name", "sop_soptask"."description", "sop_soptask"."m...p_soptask"."previous_version_id", "sop_soptask"."shared_file_id" FROM "sop_soptask" ORDER BY "sop_soptask"."order" ASC'
params = ()
ignored_wrapper_args = (False, {'connection': <DatabaseWrapper vendor='postgresql' alias='default'>, 'cursor': <django.db.backends.utils.CursorWrapper object at 0x139a0a610>})

    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 sop_soptask.media_file does not exist
E               LINE 1: ...sop_soptask"."name", "sop_soptask"."description", "sop_sopta...
E                                                                            ^
E               HINT:  Perhaps you meant to reference the column "sop_soptask.media_file_id".

Hopefully this is just something silly i have done but otherwise might be something bigger.

I have exactly the same issue, after adding new migration, somehow pytest doesn't run it.
I'm using the newest version (4.7.0) and tried basically everything, only --no-migrations makes the test pass but that's no solution.

I am experiencing the same issue and it appears that there are no answers for it.

Seems like this could be a duplicate of #1045? If so, the unifying issue seems to be having a RunPython operation that relies on a model whose field is added in a previous migration and removed in a later migration. (Maybe some optimization is detecting the field is removed later and just never adding it?) --no-migrations appears to be the only workaround, which, agreed, is not a solution.

I also faced this issue. I recommend to use django-admin command instead of migration.

It's not also the exact solution, but we can avoid the error.