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-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'),
       ]
Вернуться на верх