Kevin
Kevin

Reputation: 427

Is there any point in defining models.Index or models.UniqueConstraint in class Meta of a Django Model, if managed = False

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

Upvotes: 2

Views: 379

Answers (1)

aaron
aaron

Reputation: 43098

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()

Upvotes: 3

Related Questions