Django case insensitive unique constraint

I want my charField to be case-insensitively unique, but I don't want to store everything lower or upper cased.

Existing solutions suggest CITextField or checking for uniqueness in the form, but I thought I should be able to do it with a UniqueConstraint, specially with Django 4.0 UniqueConstrain expressions new feature. But with these code:

class Tag(models.Model):
    title = models.CharField(max_length=24, unique=True)
    ...
    class Meta:
        ordering = ['title']
        constraints = [
            models.UniqueConstraint(
                Lower('title'),
                name='unique case insensitive title'
            ),
        ]

I get this error when running migrate command. (makemigrations works fine)

...
  File "<project_path>/venv/lib/python3.8/site-packages/django/db/backends/sqlite3/schema.py", line 282, in _remake_table
    self.create_model(new_model)
  File "<project_path>/venv/lib/python3.8/site-packages/django/db/backends/base/schema.py", line 353, in create_model
    sql, params = self.table_sql(model)
  File "<project_path>/venv/lib/python3.8/site-packages/django/db/backends/base/schema.py", line 202, in table_sql
    constraints = [constraint.constraint_sql(model, self) for constraint in model._meta.constraints]
  File "<project_path>/venv/lib/python3.8/site-packages/django/db/backends/base/schema.py", line 202, in <listcomp>
    constraints = [constraint.constraint_sql(model, self) for constraint in model._meta.constraints]
  File "<project_path>/venv/lib/python3.8/site-packages/django/db/models/constraints.py", line 188, in constraint_sql
    fields = [model._meta.get_field(field_name) for field_name in self.fields]
  File "<project_path>/venv/lib/python3.8/site-packages/django/db/models/constraints.py", line 188, in <listcomp>
    fields = [model._meta.get_field(field_name) for field_name in self.fields]
  File "<project_path>/venv/lib/python3.8/site-packages/django/db/models/options.py", line 610, in get_field
    raise FieldDoesNotExist("%s has no field named '%s'" % (self.object_name, field_name))
django.core.exceptions.FieldDoesNotExist: NewTag has no field named 'Lower(F(title))'

What I'm doing wrong? Is it possible to set case-insensitive uniqueness on model level in Django without depending on PostgreSQL?

I'm currently using SQLite.

Back to Top