Home > Mobile >  Is there any point in defining models.Index or models.UniqueConstraint in class Meta of a Django Mod
Is there any point in defining models.Index or models.UniqueConstraint in class Meta of a Django Mod

Time:11-05

I'm trying to configure Django models with a legacy database. After running inspectdb I've started going through the recommended basic clean up steps (ie rearrange models' order, make sure each model has a primary key, foreign keys 'on delete', etc.). I've decided to keep managed = False in class Meta in each model to avoid migration issues with legacy app that it may cause.

In addition to the basic cleanup steps I'm wondering if it's recommended or necessary at all to add models.Index and models.UniqueConstraints to class Meta for my tables that already have these indexes and constraints defined in the database. Are these specific (class Meta) settings only needed for migrations or does Django use them to enforce constraints and for indexing at the app level in addition to what my database server (mysql 5.7) already is designed to do?

For example, here's a table with an index on a column named PAYMENT_METHOD:

accounts | CREATE TABLE `accounts` (
  `ACCOUNT_NUMBER` int(11) NOT NULL,
  `ACCOUNT_NAME` varchar(40) COLLATE utf8mb4_unicode_ci DEFAULT NULL,
  `PAYMENT_METHOD` int(11) DEFAULT NULL,
  `FLAGGED` tinyint(1) DEFAULT NULL,
  PRIMARY KEY (`ACCOUNT_NUMBER`),
  KEY `a_pm_ix` (`PAYMENT_METHOD`)
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_unicode_ci

So is it necessary to define meta Class with something like:

class Accounts(models.Model):
    account_number = models.IntegerField(db_column='ACCOUNT_NUMBER', primary_key=True)  
    account_name = models.CharField(db_column='ACCOUNT_NAME', max_length=40, blank=True, null=True)  
    payment_method = models.IntegerField(db_column='PAYMENT_METHOD', blank=True, null=True)  
    flagged = models.BooleanField(db_column='FLAGGED', blank=True, null=True)  

    class Meta:
        managed = False
        app_label = 'schoolsys'
        db_table = 'accounts'
        indexes = [
            models.Index(fields=['PAYMENT_METHOD'], name='payment_method_idx')
        ]

Or if a table has a unique constraint like this:

system_users | CREATE TABLE `system_users` (
  `USER_ID` int(11) NOT NULL,
  `USER_NAME` varchar(20) COLLATE utf8mb4_unicode_ci DEFAULT NULL,
  `PASSWORD` varchar(40) COLLATE utf8mb4_unicode_ci DEFAULT NULL,
  `MGR_CODE` varchar(20) COLLATE utf8mb4_unicode_ci DEFAULT NULL,
  `IS_ADMIN` tinyint(1) DEFAULT NULL,
  PRIMARY KEY (`USER_ID`),
  UNIQUE KEY `USER_NAME` (`USER_NAME`),
  KEY `su_un_ix` (`USER_NAME`)
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_unicode_ci

Is it necessary to define meta Class with something like:

class SystemUsers(models.Model):
    user_id = models.IntegerField(db_column='USER_ID', primary_key=True)  
    user_name = models.CharField(db_column='USER_NAME', unique=True, max_length=20, blank=True, null=True)  
    password = models.CharField(db_column='PASSWORD', max_length=40, blank=True, null=True)  
    mgr_code = models.CharField(db_column='MGR_CODE', max_length=20, blank=True, null=True)  
    is_admin = models.BooleanField(db_column='IS_ADMIN', blank=True, null=True)

    class Meta:
        managed = False
        app_label = 'schoolsys'
        db_table = 'system_users'
        constraints = [
            models.UniqueConstraint(fields=['USER_NAME'], name='unique_username')
        ]        
        indexes = [
            models.Index(fields=['USER_NAME'], name='user_name_idx')
        ]
        

CodePudding user response:

Is it necessary ...

No.

Is there any point in defining ...

Yes and no, in addition to functioning as hints to other developers.

Indexes

Options: indexes / index_together

Not at runtime. This is only used in two places:

  1. Migrations

  2. Checks - Models

Unique constraints

Options: constraints / unique_together

Yes. In addition to the two places that indexes are used, this is also used in:

  1. Form and field validationModel instance reference - django.db.models.Model.validate_unique
    • Call chain: form.is_valid()form.full_clean() → ... → self.instance.validate_unique()
  • Related