You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

禁用迁移后,Django测试如何使用PostgreSQL扩展?

解决方案:禁用测试迁移后PostgreSQL扩展依赖问题处理

问题背景

现有Django项目添加测试步骤时,因历史迁移量大,禁用了测试迁移:

DATABASES['default']['TEST'] = {
    'MIGRATE': False,
}

但项目依赖PostgreSQL的gin_trgm_ops扩展(用于模型的GinIndex):

class Meta:
    verbose_name = 'PriceBook Cache'
    verbose_name_plural = 'PriceBook Caches'
    indexes = [
        GinIndex(
            name="pricebookcache_gin_trgm_idx",
            fields=['itemid', 'itemdescription', 'manufacturerpartnumber', 'vendor_id'],
            opclasses=['gin_trgm_ops', 'gin_trgm_ops', 'gin_trgm_ops', 'gin_trgm_ops']
        ),
    ]

运行测试时触发错误:

psycopg2.errors.UndefinedObject: operator class "gin_trgm_ops" does not exist for access method "gin"

需求:不执行全量迁移初始化测试库,也不想用模板数据库/外部fixture,寻求替代方案。

可行解决方案

1. 手动在测试库创建所需扩展

通过Django测试生命周期钩子,在测试开始前执行SQL创建pg_trgm扩展,无需启动全量迁移:

  • 基础测试类初始化
    定义所有测试类的父类,在类初始化时创建扩展:
from django.test import TestCase
from django.db import connection

class BaseTestCase(TestCase):
    @classmethod
    def setUpClass(cls):
        super().setUpClass()
        with connection.cursor() as cursor:
            cursor.execute("CREATE EXTENSION IF NOT EXISTS pg_trgm;")

所有业务测试类继承BaseTestCase即可。

  • 自定义测试运行器
    全局统一处理测试库初始化,创建test_runner.py:
from django.test.runner import DiscoverRunner

class CustomTestRunner(DiscoverRunner):
    def setup_databases(self, **kwargs):
        # 先完成默认数据库初始化
        result = super().setup_databases(**kwargs)
        # 创建所需扩展
        with self.connection.cursor() as cursor:
            cursor.execute("CREATE EXTENSION IF NOT EXISTS pg_trgm;")
        return result

在settings.py中指定测试运行器:

TEST_RUNNER = 'your_project.test_runner.CustomTestRunner'

2. 为测试创建独立的极简迁移

创建仅包含扩展和核心表结构的测试专用迁移集,避免执行历史全量迁移:

  1. 新建测试迁移目录,在settings.py中配置:
TEST_MIGRATION_MODULES = {
    'your_app': 'tests.migrations',
}
  1. 生成仅包含当前模型结构的初始迁移:
python manage.py makemigrations your_app --name test_initial
  1. 编辑生成的迁移文件,添加扩展创建操作:
from django.db import migrations

class Migration(migrations.Migration):
    initial = True

    dependencies = []

    operations = [
        migrations.RunSQL("CREATE EXTENSION IF NOT EXISTS pg_trgm;"),
        # 保留自动生成的模型表创建操作
    ]
  1. 测试时启用迁移,但指定使用测试专用迁移:
DATABASES['default']['TEST'] = {
    'MIGRATE': True,
    'MIGRATION_MODULES': TEST_MIGRATION_MODULES,
}

3. 使用第三方库简化扩展管理

如果项目依赖多个PostgreSQL扩展,可使用django-postgres-extra库,通过模型Meta类声明扩展依赖,自动处理初始化:

安装后,修改模型类:

from django_postgres_extensions.models import PostgresModel

class PriceBookCache(PostgresModel):
    # 模型字段定义...
    class Meta:
        verbose_name = 'PriceBook Cache'
        verbose_name_plural = 'PriceBook Caches'
        indexes = [
            GinIndex(
                name="pricebookcache_gin_trgm_idx",
                fields=['itemid', 'itemdescription', 'manufacturerpartnumber', 'vendor_id'],
                opclasses=['gin_trgm_ops', 'gin_trgm_ops', 'gin_trgm_ops', 'gin_trgm_ops']
            ),
        ]
        required_extensions = ['pg_trgm']

库会在测试初始化时自动创建所需扩展,配合禁用全量迁移的设置即可正常运行测试。


内容的提问来源于stack exchange,提问作者James Lin

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.08.11 19:45:30