Почему 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
файл, если он присутствует. В противном случае будет сделано исключение.
Чтобы избежать ненужных миграций, вы можете сделать следующее:
- Поле подкласса, которое вызывает миграцию
- Написать собственный метод деконструкции внутри этого поля
- прибыль
Пример:
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
исправляет это.