【问题标题】:Django create unique function indexDjango 创建唯一函数索引
【发布时间】:2021-10-30 14:56:19
【问题描述】:

使用 postgresql 我们可以创建唯一的函数索引:

create unique index user_date_checkin
on unique_user_date (user_id, (timezone('UTC'::text, create_time)::date));

但是使用 Django 3.2:

class UserCheckin(GeneralModel):
   id = models.BigAutoField(primary_key=True)
   user_id = models.BigIntegerField()
   create_time = models.DateTimeField()
   
   class Meta:
       indexes = [
           models.Index("user_id", TruncDate("create_time"), name="user_date_checkin"),
        ]

只能得到这样的sql生成:

create index user_date_checkin
    on test (user_id, (timezone('UTC'::text, create_time)::date));

还有UniqueConstraint

constraints = [
    models.UniqueConstraint(
        fields=["user_id", TruncDate("create_time")],
        name="user_date"),
]

得到refers to the nonexistent field 'TruncDate(F(create_time)) 错误

那么如何在 Django 3.2 中创建具有函数的唯一索引?

更新

在django源码django/db/backends/base/schema.py我发现:

    if condition or include or opclasses:
        sql = self.sql_create_unique_index
    else:
        sql = self.sql_create_unique

但在这种情况下我没有这样的条件或操作类

更新

添加条件后:

    indexes = [
        models.Index("user_id", TruncDate("create_time"),
            condition=Q(user_id__isnull=False), name="user_date_checkin"),
    ]

还是不要在此处添加unique

-- auto-generated definition
create index user_date_checkin
    on voip_usercheckin (user_id, (timezone('UTC'::text, create_time)::date))
    where (user_id IS NOT NULL);

【问题讨论】:

    标签: django postgresql django-models


    【解决方案1】:

    Django 还不支持功能约束。但这个功能已经在development 中,并将成为预计于 2021 年 12 月发布的 Django 4.0 版的一部分。现在您可以通过自定义迁移来执行您的 sql:

    首先运行python manage.py makemigrations yourapp --empty,其中yourapp 是您拥有模型的应用程序。接下来编辑生成的迁移并添加RunSQL [Django-docs] 操作:

    from django.db import migrations, models
    
    
    class Migration(migrations.Migration):
    
        dependencies = [
            ...
        ]
    
        operations = [
            migrations.RunSQL(
                sql="create unique index user_date_checkin on unique_user_date (user_id, (timezone('UTC'::text, create_time)::date));",
                reverse_sql="DROP INDEX IF EXISTS user_date_checkin;"
            ),
        ]
    

    之后,您可以通过运行python manage.py migrate 应用此迁移,这将在数据库中创建索引。


    在 Django 4.0 发布后,您可能(可能会更改)编写以下内容:

    constraints = [
        models.UniqueConstraint(
            "user_id",
            TruncDate("create_time"),
            name="user_date"),
    ]
    

    【讨论】:

      猜你喜欢
      • 2010-12-07
      • 2018-05-27
      • 2021-06-22
      • 1970-01-01
      • 1970-01-01
      • 2019-12-04
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多