Подтвердить что ты не робот

Почему 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?

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

4b9b3361

Ответ 1

Вы можете выполнить сквош с предыдущей миграцией.

Если вы вообще не хотите выводить эти миграции, вы можете переопределить команду 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

Ответ 2

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

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

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

Ответ 3

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

  • Поле подкласса, вызывающее миграцию
  • Создать собственный метод деконструирования внутри этого поля
  • Profit

Пример:

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

Надеюсь, что поможет

Ответ 4

Как @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.

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

Ответ 5

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

Все, что вам нужно, это сохранить его в некоторых файлах 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

Ответ 6

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

Поэтому, поскольку я не нашел решения для Django 1.9.13, я добавил небольшой взлом в settings.py:

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

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

Ответ 7

В Django 2.X это исправлено с помощью ugettext_lazy вместо ugettext или gettext.