Django: Добавьте уникальный индекс для выражений в postgres
Рассмотрим модель django -
class Students(models.Model)
id = models.BigAutoField(primary_key=True)
scoreA = models.CharField(null=True, max_length=15)
scoreB = models.CharField(null=True, max_length=15)
Я хочу добавить этот уникальный индекс.
create unique index unq_idx on students ((case when scoreA is not NULL then scoreA else '' end), (case when scoreB is not NULL then scoreB else '' end));
Как мне добавить его через django ORM?
Я использую Django 3.1 с postgres 12.1
В данном случае требуется уникальное ограничение для двух полей, которое не допускает множественных значений NULL (Link)
Начиная с версии django-4.0, появится возможность делать функциональные уникальные ограничения [Django-doc]. В этом случае вы можете определить такое ограничение следующим образом:
from django.db.models import UniqueConstraint, Value
from django.db.models.functions import Coalesce
class Students(models.Model)
id = models.BigAutoField(primary_key=True)
scoreA = models.CharField(null=True, max_length=15)
scoreB = models.CharField(null=True, max_length=15)
class Meta:
constraints = [
UniqueConstraint(Coalesce('scoreA', Value('')), Coalesce('scoreB', Value('')), name='unique_score_combo')
]
Заработал с Django 3.2, используя Index.expressions и твик UniqueIndex из django-postgres-extra
class Students(models.Model)
id = models.BigAutoField(primary_key=True)
scoreA = models.CharField(null=True, max_length=15)
scoreB = models.CharField(null=True, max_length=15)
class Meta:
indexes = [
UniqueIndex(
Case(When(scoreA__isnull=False, then=F('scoreA')), default=Value('')),
Case(When(scoreB__isnull=False, then=F('scoreB')), default=Value('')),
name='unique_idx'),
]