Home > Enterprise >  Django postgres unique constraint name generation
Django postgres unique constraint name generation

Time:02-15

When adding a new unique constraint on a django model, this will automatically create a name for this constraint in postgres. Does Postgres generate this name or is it Django? Is it deterministic?

for example I use this model

class MyModel(Model):
  field1 = TextField()
  field2 = IntegerField()

  class Meta:
    unique_together = ("field1", "field2")

I got the name of the constraint with

select constraint_name
from information_schema.constraint_column_usage
where table_name = 'myapp_mytable'

I get a name like field1_field2_d04755de_uniq

CodePudding user response:

Django will determine this name. Indeed, the source code [GitHub] shows that it determines the name with:

if name is None:
    name = IndexName(table, columns, "_uniq", create_unique_name)

The IndexName [GitHub] will call create_unique_name with the table, columns and suffix:

class IndexName(TableColumns):
    
    def __init__(self, table, columns, suffix, create_index_name):
        # …
        pass

    def __str__(self):
        return self.create_index_name(self.table, self.columns, self.suffix)

and the create_unique_name will return a quoted version of _create_index_name, which will make a digest of the table_name and column_names [GitHub]:

def _create_index_name(self, table_name, column_names, suffix=""):
    # …
    _, table_name = split_identifier(table_name)
    hash_suffix_part = "%s%s" % (
        names_digest(table_name, *column_names, length=8),
        suffix,
    )
    # …

But using unique_together is likely to become deprecated. Indeed, the documentation on unique_together says:

Use UniqueConstraint with the constraints option instead.

UniqueConstraint provides more functionality than unique_together. unique_together may be deprecated in the future.

You can define this UniqueConstraint where you can also manually specify the name of the constraint:

from django.db import models

class MyModel(models.Model):
    field1 = models.TextField()
    field2 = models.IntegerField()

    class Meta:
        constraints = [
            models.UniqueConstraint(fields=('field1', 'field2'), name='some_constraint_name')
        ]

CodePudding user response:

As suggested by @willem-van-onsem, using UniqueConstraint allows to set the constraint name (which is pretty deterministic)

  • Related