Django3.2如何创建PostgreSQL基于函数的唯一索引
问题原因
你之前把 TruncDate 表达式放到了 UniqueConstraint 的 fields 参数里,fields 参数仅支持传入字符串格式的模型字段名,不支持数据库函数/表达式,所以会报字段不存在的错误。
正确实现方案
Django 3.2 中 UniqueConstraint 支持 expressions 参数专门用于实现基于函数/表达式的唯一约束,配置如下:
首先导入依赖:
import datetime from django.db import models from django.db.models import UniqueConstraint, TruncDate
修改模型的Meta配置:
class UserCheckin(GeneralModel): id = models.BigAutoField(primary_key=True) user_id = models.BigIntegerField() create_time = models.DateTimeField() class Meta: constraints = [ UniqueConstraint( expressions=[ "user_id", # 指定UTC时区,保证和原生SQL逻辑完全一致 TruncDate("create_time", tzinfo=datetime.timezone.utc) ], name="user_date_checkin", # 可选:如果需要添加过滤条件,加condition参数即可 # condition=models.Q(user_id__isnull=False) ) ]
执行迁移后生成的SQL和你手写的原生SQL完全一致:
create unique index user_date_checkin on usercheckin (user_id, (timezone('UTC'::text, create_time)::date));
备选方案
如果有特殊场景ORM无法满足,也可以手动创建迁移文件,通过RunSQL执行原生SQL语句:
from django.db import migrations class Migration(migrations.Migration): dependencies = [ ("your_app_name", "000x_previous_migration_number"), ] operations = [ migrations.RunSQL( sql=""" create unique index user_date_checkin on usercheckin (user_id, (timezone('UTC'::text, create_time)::date)); """, reverse_sql="drop index user_date_checkin;" ) ]
内容的提问来源于stack exchange,提问作者jiamo
相关产品推荐
相关产品推荐

