Создает ли Django бесполезные миграции? - PullRequest
3 голосов
/ 25 октября 2019

Когда я изменяю атрибут verbose_name модели Django, Django генерирует связанную миграцию (запускает команду make migrations).

Однако без применения миграции (команда migrate)Изменения, кажется, применяются во всем проекте Django. Я думаю, это потому, что verbose_name используется на уровне Django, а не на уровне базы данных.

Это заставляет меня задуматься: какова цель этого файла миграции?

1 Ответ

4 голосов
/ 25 октября 2019

Джанго делает абстракцию используемого бэкэнда. Действительно, вы можете использовать другой бэкэнд, изменив файл settings.py. Фактически вы можете определить бэкэнд самостоятельно.

Все изменения в моделях, таким образом могут повлиять на базу данных. Например, вы можете определить бэкэнд, который использует verbose_name столбца в качестве «строки комментария», которую вы часто можете добавлять в такой столбец на стороне базы данных. Например, если вы определите choices, то для некоторых баз данных бэкэнд может попытаться применить эти варианты на уровне базы данных.

Поскольку, как уже было сказано, Django стремится работать без знания используемого бэкэнда, онтаким образом, стремится быть консервативным и выполнять миграции для большого количества модельных изменений. Для некоторых из них сервер решит просто ничего не делать 1011 *. Таким образом, запрос не создается, и ничего не меняется на стороне базы данных. Вы действительно можете увидеть такие изменения как «бесполезные миграции». Но имейте в виду, что если позже вы будете использовать другой бэкэнд, эти «бесполезные миграции» могут на самом деле что-то делать.

Поскольку такие миграции ничего не делают на стороне базы данных, они, однако, обычно не занимают много времени. ,Возможно, вы захотите посмотреть вместе файлы миграции " squash " [Django-doc] и таким образом уменьшить количество используемых файлов миграции. Миграции по-прежнему будут частью файла, но так как в этом нет никаких запросов, это, как правило, не принесет большого вреда.

Кроме того, вы можете на самом деле исправить функцию deconstruct на поле, так чтоhelp_text и т. д. больше не появляются в результате вызова deconstruct и, следовательно, не видны «детектору». Этот скрипт Gist показывает способ исправления команды makemigration:

"""
Patch the creation of database migrations in Django
Import this early from `__init__.py``.
- Don't want verbose_name changes in the migrations file.
- Don't want help_text in the migrations file.
"""
from functools import wraps

from django.db.models import Field


def patch_deconstruct(old_func, condition):
    """
    Patch the ``Field.deconstruct`` to remove useless information.
    This only happens on internal apps, not third party apps.
    """

    @wraps(old_func)
    def new_deconstruct(self):
        name, path, args, kwargs = old_func(self)
        # AutoField has no model on creation, but can be skipped
        if hasattr(self, 'model') and condition(self):
            kwargs.pop('verbose_name', None)
            kwargs.pop('help_text', None)
        return name, path, args, kwargs
    return new_deconstruct


Field.deconstruct = patch_deconstruct(Field.deconstruct, lambda self: self.model.__module__.startswith('apps.'))
...