2014-10-22 2 views
23

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

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

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

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

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

+2

Этот комментарий от andrewgodwin отвечает на вопрос частично, но Я все еще хочу иметь возможность изменять 'help_text', не требуя обновления миграций: https://code.djangoproject.com/ticket/21498#comment:6 – utapyngo

ответ

7

This ticket обратился к проблеме.

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

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

4

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

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

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

1

Как @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 файлы везде на пути

+0

Исходный вопрос был о' makemigrations', а не 'maketranslations'. – utapyngo

+0

Спасибо за указание моей опечатки – katomaso

0

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

Все, что вам нужно это, чтобы сохранить его в некоторых Utils/моделей.дб и во всех ваших моделях вместо 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 
8

Вы можете squash it with the previous migration, конечно.

Или, если вы не хотите, чтобы вывести эти миграции на всех, вы можете изменить команду 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 
+0

Спасибо за указание этого! Кажется настолько очевидным после факта. Это философская вещь для некоторых (полные миграции); это хорошо в теории, за исключением того, что на практике это не работает. Особенно с помощью help_text, выбора и 'хранения'! Наш менеджер хранения и путь определяется во время выполнения, поэтому ... что, вы хотите, чтобы я сделал поддельное хранилище для миграции? Гах. Это решает его ... отдельные проблемы времени выполнения от проблем модели, как и должно быть. –