Django ManyToMany через индексацию моделей/таблиц

Для ManyToMany отношений Django автоматически создаст корыто модели/таблицы.

Например, для:

class Magazine(models.Model):
    pass


class Article(models.Model):
    magazines = models.ManyToManyField('Magazine', related_name='articles')

будет Article.through менеджер и модель. Связанная таблица будет иметь два отдельных индекса для каждого из столбцов. Два вопроса:

  1. Как создать новый индекс для обоих столбцов? Я мог бы выполнить необработанный SQL-запрос, чтобы сделать это, но мне интересно, есть ли способ сделать что-то похожее на то, как index_together, который легко поддерживать и отслеживать.
  2. Есть ли причина, по которой Django не добавляет автоматически индекс к обоим столбцам? В моем тесте я вручную создал индекс и увидел, что Postgres сильно увеличил его и производительность.

Если вы хотите внести изменения в промежуточную таблицу, используемую полем ManyToManyField, вы можете использовать аргумент through для поля. Это позволит вам вручную определить промежуточную модель, в которую можно добавить многостолбцовый индекс. Обратите внимание, что index_together был устаревшим в пользу indexes.

Вот простой пример того, как выглядит добавление многоколоночного индекса в промежуточную таблицу, заданную вручную.

class Magazine(models.Model):
    pass


class Article(models.Model):
    magazines = models.ManyToManyField('Magazine', related_name='articles', through='MagazineArticle')


class MagazineArticle(models.Model):
    magazine = models.ForeignKey('Magazine')
    article = models.ForeignKey('Article')

    class Meta:
        indexes = [
            models.Index(fields=["magazine", "article"])
        [

Я не могу сказать, почему Django не создает этот индекс автоматически, но, по крайней мере, есть простой способ добавить его!

Документация:

ManyToManyField через аргумент

Индексы мета-опции

Чтобы создать составной индекс по обоим столбцам:

Вы определяете свою собственную сквозную модель

class Magazine(models.Model):
        pass

class Article(models.Model):
        magazines = models.ManyToManyField('Magazine', 
                                             through='MagazineArticle',
                                             related_name='articles')
            
        
class MagazineArticle(models.Model):
        article = models.ForeignKey(Article, on_delete=models.CASCADE)
        magazine = models.ForeignKey(Magazine, on_delete=models.CASCADE)
            
        class Meta:
            indexes = [
                    models.Index(fields=['article', 'magazine'])
                ]
        
        
Вернуться на верх