DEV Community

Discussion on: Django: Why you might want to set up extra DB level indexes for your ManyToMany relationships

karolyi profile image
László Károlyi Author

Oh, I almost forgot to reply to you.

In my under the django module that contains the with the model, I added the following functions, which is a result of me experimenting around until I found out the right way of doing it. It is basically putting together the SQL for creating the index via MariaDB:

from django.apps import AppConfig
from django.conf import settings
from django.core.checks import Info, Tags, register
from django.db import connection
from django.db.models.signals import post_migrate
from django.db.utils import OperationalError
from django.utils.translation import ugettext_lazy as _

def add_applieddiscount_sr_index() -> list:
    As discussed in the link below, add an index to `seatreservation_id`
    on the `ManyToMany` `AppliedDiscount` relation.
    from .models import SeatReservation
    errors = []
    m2m_model = SeatReservation.applied_discounts.through
    db_table = m2m_model._meta.db_table
    field_name = m2m_model._meta.get_field('seatreservation').column
    cursor = connection.cursor()
            f'ALTER TABLE `{db_table}` ADD INDEX sr_id_index (`{field_name}`)')
    except OperationalError as exc:
        if exc.args[0] == settings.MARIADB_INDEX_ALREADY_EXISTS_CODE:
            # Index already exists
            return errors
    errors.append(Info(msg='Added index on SeatReservation.applied_discounts'))
    return errors

def post_migrate_ensure_defaults(**kwargs):
    Run the default models installer when it is our application's
    `post_migrate` signal.
    if not isinstance(kwargs['sender'], BookingConfig):
        # Running from migration post-signal, but not from our app's
        # signal
    return ensure_defaults()

def ensure_defaults(**kwargs):
    'Run the default setter and maintenance functions.'
    errors = []
    return errors

class BookingConfig(AppConfig):
    name = f''
    verbose_name = _('Project: Booking')
    label = f'project_booking'

    def ready(self):
        'Fix database, run maintenance scripts, etc ...'
        register(ensure_defaults, Tags.models)

Also, you'll have to modify the next to the to contain the following lines:

from django.conf import settings

default_app_config = ''

Where the path in default_app_config is the python import path to your