25

I am trying to add indexes on model fields using Field.db_index for an app that has migrations. Looking at Django's documentation all I need to do is to set db_index=True:

class Person(models.Model):
    first_name = models.CharField()
    last_name = models.CharField(db_index=True)

and then I first tried the new Django's Migration:

./manage.py makemigrations app-name

but Migration does not seem to notice the change and does not add the sql command for creating an index. So I tried django-admin.py as explained here:

django-admin.py sqlindexes app-name

But that does not print the sql command either and it exits with the following error:

CommandError: App 'app-name' has migrations. Only the sqlmigrate and sqlflush commands can be used when an app has migrations.

3 Answers 3

27

This problem still exists in django2.1. I solved it by using the indexes Meta option. This is a bit cleaner than the index_together solution.

class Person(models.Model):
    first_name = models.CharField()
    last_name = models.CharField()

    class Meta:
        indexes = [
            models.Index(fields=['last_name']),
        ]
Sign up to request clarification or add additional context in comments.

Comments

10

OK, I managed to create the indexes using Meta.index_together. It is not the cleanest way, since I am not actually indexing multiple fields together but it works with makemigrations:

class Person(models.Model):
    class Meta():
        index_together = [['last_name']]
    first_name = models.CharField()
    last_name = models.CharField()

Now makemigrations does make a new migration:

./manage.py makemigrations app-name

>>Migrations for 'app-name':
>>  0005_auto_20140929_1540.py:
>>    - Alter index_together for Person (1 constraint(s))

And the corresponding sql command is actually CREATE INDEX.

./manage.py sqlmigrate app-name 0005_auto_20140929_1540

>>BEGIN;
>>CREATE INDEX app-name_person_last_name_7...4_idx ON `app-name_person` (`last_name`);
>>COMMIT;

Comments

9

You can do this explicitly in your migration using Django's AddIndex and Index classes.

First create an empty migration with manage.py makemigrations --empty and then simply fill it out as follows:

from django.db import migrations
from django.db.models.indexes import Index
from django.db.migrations import AddIndex


class Migration(migrations.Migration):

    dependencies = [
        ('app_name', 'ref_to_previous_migration'),
    ]

    operations = [
        AddIndex('ModelName', Index(fields=['field_name'], name='my_index'))
    ]

You can use options on the Index class to specify fields, add a name, and do special custom things like index only part of the table, etc. Check the doc links above.

Comments

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.