Почему Django выполняет миграцию для изменений help_text и verbose_name?

Когда я меняюсь help_text или же verbose_name для любого из моих полей модели и запустить python manage.py makemigrations, он обнаруживает эти изменения и создает новую миграцию, скажем, 0002_xxxx.py,

Я использую PostgreSQL и думаю, что эти изменения не имеют отношения к моей базе данных (мне интересно, существует ли вообще СУБД, для которой эти изменения актуальны).

Почему Django генерирует миграции для таких изменений? Есть ли возможность игнорировать их?

Могу ли я применить изменения из 0002_xxxx.py к предыдущей миграции (0001_initial.py) вручную и безопасно удалить 0002_xxxx.py?

Есть ли способ автоматически обновить предыдущую миграцию?

6 ответов

Вы можете раздавить это с предыдущей миграцией, конечно.

Или, если вы вообще не хотите выводить эти миграции, вы можете переопределить makemigrations а также migrate Команда, поставив это в management/commands/makemigrations.py в вашем приложении:

from django.core.management.commands.makemigrations import Command
from django.db import models

IGNORED_ATTRS = ['verbose_name', 'help_text', 'choices']

original_deconstruct = models.Field.deconstruct

def new_deconstruct(self):
  name, path, args, kwargs = original_deconstruct(self)
  for attr in IGNORED_ATTRS:
    kwargs.pop(attr, None)
  return name, path, args, kwargs

models.Field.deconstruct = new_deconstruct

Этот билет решает проблему.

Если вы изменились только help_text & django создает новую миграцию; затем вы можете применить изменения от последней миграции к предыдущей миграции и удалить последнюю миграцию.

Просто измените help_text в предыдущей миграции help_text присутствует в последней миграции и удаляет последний файл миграции. Убедитесь, что удалили соответствующие *.pyc файл, если он присутствует. В противном случае будет сделано исключение.

Чтобы избежать ненужных миграций, вы можете сделать следующее:

  1. Поле подкласса, которое вызывает миграцию
  2. Написать собственный метод деконструкции внутри этого поля
  3. прибыль

Пример:

from django.db import models

class CustomCharField(models.CharField):  # or any other field

    def deconstruct(self):
        name, path, args, kwargs = super(CustomCharField, self).deconstruct()
        # exclude all fields you dont want to cause migration, my example below:
        if 'help_text' in kwargs:
            del kwargs['help_text']
        if 'verbose_name' in kwargs:
            del kwargs['verbose_name']
        return name, path, args, kwargs

надеюсь, это поможет

Как заметил @ChillarAnand, есть решение этой проблемы, но до сих пор (django 1.9.1) команды миграции не были исправлены.

Наименее навязчивый способ исправить это создать свой собственный maketranslatedmigrations команда в <your-project>/management/commands/maketranslatedmigrations.py как

#coding: utf-8

from django.core.management.base import BaseCommand
from django.core.management.commands.makemigrations import Command as MakeMigrations


class Command(MakeMigrations):
    leave_locale_alone = True
    can_import_settings = True

    def handle(self, *app_labels, **options):
        super(Command, self).handle(*app_labels, **options)

И тогда вы можете использовать его точно так же, как оригинальные makemigrations.

PS Не забудьте добавить __init__.py файлы везде на пути

Билет, который упоминает ChillarAnand, очень полезен, но в финале журнала изменений я не понял, было ли это исправлено или нет, или это было исправлено в новейшей версии Django.

Итак, из-за того, что я не нашел никакого решения для Django 1.9.13, я добавил небольшой взломать settings.py:

if 'makemigrations' in sys.argv:
    USE_I18N = False
    USE_L10N = False

Не элегантно, но работает нормально.

Прекратите создание файлов миграции при изменении verbose_name или verbose_name_plural в любом из полей вашей модели.

В новом файле, таком как src / monkey_patching/django/db/migrations/operations/change_model_options.py, добавьте это:

from django.db.migrations.operations import models

models.AlterModelOptions.ALTER_OPTION_KEYS = [
    "base_manager_name",
    "default_manager_name",
    "get_latest_by",
    "managed",
    "ordering",
    "permissions",
    "default_permissions",
    "select_on_save",
    # "verbose_name",
    # "verbose_name_plural",
]

Проверено в django 1.11.10.

Я написал специальный модуль для этой цели

Все, что вам нужно, это сохранить его в некоторых utils/models.db и во всех ваших моделях вместо from django.db import models записывать from utils import models

Если кому-то это интересно, я могу написать компонент и опубликовать его на pypi

UPD: попробуйте это https://github.com/FeroxTL/django-migration-control

# models.py

# -*- coding: utf-8 -*-
from types import FunctionType
from django.db import models


class NoMigrateMixin(object):
    """
    Позволяет исключить из миграций различные поля
    """
    def deconstruct(self):
        name, path, args, kwargs = super(NoMigrateMixin, self).deconstruct()
        kwargs.pop('help_text', None)
        kwargs.pop('verbose_name', None)
        return name, path, args, kwargs


# =============================================================================
# DJANGO CLASSES
# =============================================================================

for name, cls in models.__dict__.items():
    if isinstance(cls, type):
        if issubclass(cls, models.Field):
            # Поля
            globals()[name] = type(name, (NoMigrateMixin, cls), {})
        else:
            # Всякие менеджеры
            globals()[name] = cls
    elif isinstance(cls, FunctionType):
        # Прочие функции
        globals()[name] = cls

Из Django 2.X, используя ugettext_lazy вместо того ugettext или gettext исправляет это.

Другие вопросы по тегам