3

Consider the django model -

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)
   

I'm looking to add this unique index.

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));

How do I add it through the django ORM ?

I'm using Django 3.1 with postgres 12.1

The use-case is to have a unique constraint over the two fields which doesn't allow multiple NULL values (Link)

2
  • In Django-3.2 you can create functional indexes, but not in 3.1. Commented Oct 26, 2021 at 10:46
  • But, even with Django-3.2, I don't see a way to create a functional unique index Commented Oct 26, 2021 at 11:14

2 Answers 2

3

As of , it will be possible to make functional unique constraints [Django-doc]. In that case you can define such constraint with:

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')
        ]
Sign up to request clarification or add additional context in comments.

Comments

2

Got it working with Django 3.2 using Index.expressions and the UniqueIndex tweak from 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'),
       ]

1 Comment

Unfortunately, as of may 17 2024, the latest stable version (v2.0.8) has been released on Feb 3, 2023... The last issue triage also dates back to February 2023. I would advise not to use django-postgres-extra within companies.

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.