如何在Django迁移的AddIndexConcurrently中添加IF NOT EXISTS条件
问题解答
首先要明确:models.Index的condition参数是用于创建**部分索引(Partial Index)**的,作用是指定仅对表中满足筛选条件的行创建索引,和你需要的IF NOT EXISTS语法没有关系,无法通过配置该参数实现需求。
Django 3.1.7版本原生的AddIndexConcurrently操作没有内置支持生成带IF NOT EXISTS的SQL语句,你可以通过以下两种方案实现需求:
方案1:直接使用自定义RunSQL操作(最简单)
直接写你需要的SQL语句作为迁移操作,注意并发创建索引不能在事务中执行,需要显式关闭事务:
database_operations = [ migrations.RunSQL( sql='CREATE INDEX CONCURRENTLY IF NOT EXISTS "chat_chatmessage_type_idx" ON "chats_chatmessage" ("type");', # 回滚语句可选,根据你的需求调整 reverse_sql='DROP INDEX IF EXISTS "chat_chatmessage_type_idx";', atomic=False ) ]
方案2:自定义支持IF NOT EXISTS的AddIndexConcurrently(适合复用)
如果你需要在多处使用该能力,可以继承原生类重写SQL模板:
from django.contrib.postgres.operations import AddIndexConcurrently as BaseAddIndexConcurrently from django.db import migrations # 自定义操作类 class AddIndexConcurrentlyIfNotExists(BaseAddIndexConcurrently): sql = "CREATE INDEX CONCURRENTLY IF NOT EXISTS %(name)s ON %(table)s (%(columns)s)%(extra)s" # 使用自定义类替代原生AddIndexConcurrently database_operations=[ AddIndexConcurrentlyIfNotExists( model_name='chatmessage', index=models.Index( fields=["type"], name="chat_chatmessage_type_idx" ) ) ]
注意事项
- 并发创建索引时禁止包裹在数据库事务中,上述两种方案都已经处理了该逻辑,无需额外配置
- 如果你后续升级到Django 4.2及以上版本,官方原生的
AddIndex操作已经内置了if_not_exists参数,可以直接配置使用,不需要自定义逻辑
内容的提问来源于stack exchange,提问作者Apyff
相关产品推荐
相关产品推荐

