django – Unique constraint with ‘ignore case’ – Education Career Blog

How to specify custom constraint for Django model?

Like that

create table t
(
  login varchar(10),
  unique ( upper(login) )
);

,

Django’s unique and unique_together support is handled at the database level, so being quite database dependent, the use of a database function in the constraint isn’t supported in Django (not all DBs may support it, or support it consistently, etc etc). You do, however, have a few choices:

The Code Way

If maintaining database portability is important, override the save() method in your model class and perform checking there in code. This is obviously a performance drain as you will have to issue a query before you issue an update/insert, but as with all things performance related, it may be best to try the simplest solution first and then see if there’s truly a performance issue for your application and deployment environment. (This is effectively what the “django-check-constraints” project that Adam Bernier pointed out in the question comments is doing… just with a level of abstraction you probably don’t need).

The SQL Way

Or, if you don’t care so much about database portability, or are happy to write the appropriate SQL for all the databases you need to support, you can take advantage of Django’s hook for running custom SQL statements after the CREATE TABLE is run for the model. The django docs cover it here: Providing Initial SQL Data.

While the example in the docs, as the title suggests, is for populating initial data using SQL, you can put any set of SQL statements in the file, including ALTER TABLE commands to introduce a DB-managed constraint with a function right after the table is created. Django lets you provide separate SQL statements for each database type you support.

Leave a Comment