Установить расширение postgresql перед pytest установить базу данных для django

Мне нужно установить расширение citext в мою базу данных postgresql для проекта django. Для самого проекта все прошло гладко и отлично работает через миграции, но мой pytest настроен с опцией --no-migrations, поэтому pytest создает базу данных без запуска миграций. Как я могу заставить pytest установить расширение postgres citext перед созданием таблиц? В настоящее время я получаю

- django.db.utils.ProgrammingError: type "citext" does not exist

пока pytest пытается создать таблицу auth_users

sql = 'CREATE TABLE "auth_user" ("id" serial NOT NULL PRIMARY KEY, "password" varchar(128) NOT NULL, "last_login" timestamp ...T NULL, "is_active" boolean NOT NULL, "date_joined" timestamp with time zone NOT NULL, "email" citext NOT NULL UNIQUE)', params = None
ignored_wrapper_args = (False, {'connection': <django.contrib.gis.db.backends.postgis.base.DatabaseWrapper object at 0x7fb313bb0100>, 'cursor': <django.db.backends.utils.CursorWrapper object at 0x7fb30d9f8580>})

Я пытался использовать приспособление django_db_setup, но не понял, как его изменить, потому что что-то вроде этого

@pytest.fixture(scope="session")
def django_db_setup(
    request,
    django_test_environment,
    django_db_blocker,
    django_db_use_migrations,
    django_db_keepdb,
    django_db_createdb,
    django_db_modify_db_settings,
):
    """Top level fixture to ensure test databases are available"""
    from django.test.utils import setup_databases, teardown_databases

    setup_databases_args = {}

    if not django_db_use_migrations:
        from pytest_django.fixtures import _disable_native_migrations
        _disable_native_migrations()

    if django_db_keepdb and not django_db_createdb:
        setup_databases_args["keepdb"] = True

    with django_db_blocker.unblock():
        from django.db import connection
        cursor = connection.cursor()
        cursor.execute("CREATE EXTENSION IF NOT EXISTS citext;")

        db_cfg = setup_databases(
            verbosity=request.config.option.verbose,
            interactive=False,
            **setup_databases_args
        )
    def teardown_database():
        with django_db_blocker.unblock():
            try:
                teardown_databases(db_cfg, verbosity=request.config.option.verbose)
            except Exception as exc:
                request.node.warn(
                    pytest.PytestWarning(
                        "Error when trying to teardown test databases: %r" % exc
                    )
                )

    if not django_db_keepdb:
        request.addfinalizer(teardown_database)

мне не помогло

К сожалению, между настройкой базы данных и загрузкой соответствующих расширений postgresql нет соответствующих крючков. Вы можете обойти эту проблему, скопировав/изменив код pytest-django, который отключает миграции, и запустив свой код вместо кода из апстрима.

@pytest.fixture(scope="session")
def django_migration_disabler() -> None:
    """Disable migrations when running django tests.

    This copies/alters the behavior of pytest_django.fixtures._disable_migrations,
    which is called when pytest is invoked with --no-migrations.

    See: https://github.com/pytest-dev/pytest-django/blob/v4.5.2/pytest_django/fixtures.py#L260

    We do this instead of invoking with --no-migrations because constructing the
    database without migrations fails to create necessary postgres extensions like
    citext and uuid-ossp.

    We then override the django_db_setup fixture and ensure that this
    fixture is called before the parent django_db_setup fixture.
    """
    from django.conf import settings
    from django.core.management.commands import migrate
    from django.db import connections

    class DisableMigrations:
        def __contains__(self, item: str) -> bool:
            return True

        def __getitem__(self, item: str) -> None:
            return None

    settings.MIGRATION_MODULES = DisableMigrations()

    class MigrateSilentCommand(migrate.Command):
        def handle(self, *args, **options):
            options["verbosity"] = 0
            database = options["database"]
            connection = connections[database]
            with connection.cursor() as cursor:
                cursor.execute('CREATE EXTENSION IF NOT EXISTS "citext";')
            return super().handle(*args, **options)

    migrate.Command = MigrateSilentCommand  # type: ignore


@pytest.fixture(scope="session")
def django_db_use_migrations() -> bool:
    """Force pytest-django to use migrations.

    This is necessary because we disable migrations in the django_migration_disabler
    and the existing pytest-django mechanisms would override our disabling mechanism
    with their own, which would fail to create the necessary extensions in postgres.
    """
    return True


@pytest.fixture(scope="session")
def django_db_setup(django_migration_disabler, django_db_setup, django_db_blocker):
    """Override django_db_setup ensuring django_migration_disabler is loaded."""
    pass
Вернуться на верх