简体   繁体   中英

Django postgres unique constraint name generation

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

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')
        ]

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

I simply add this to migrations:

...
        migrations.RunSQL("""
            ALTER TABLE IF EXISTS public.api_sectoraltr
                ADD UNIQUE (year, category_id, code_id);
        """, reverse_sql=migrations.RunSQL.noop),
...

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM