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

Остановить Django от создания миграции, если список вариантов изменения поля

У меня есть приложение ядра django, называемое "foocore" .

Существует несколько дополнительных подключаемых приложений. Например, "superfoo".

В моем случае каждый плагин добавляет новый выбор в модель CharField, которая принадлежит к "foocore" .

Миграции Django обнаруживают изменения, если список вариантов изменяется.

Я думаю, что это не обязательно. По крайней мере один другой разработчик думает так же:

https://code.djangoproject.com/ticket/22837

class ActivePlugin(models.Model):
    plugin_name = models.CharField(max_length=32, choices=get_active_plugins())

Код для выбора:

class get_active_plugins(object):
    def __iter__(self):
        for item in ....:
            yield item

Ядро "foocore" используется в нескольких проектах, и каждая установка имеет другой набор плагинов. Django пытается создать бесполезные миграции....

Есть ли способ обойти это?

4b9b3361

Ответ 1

См. этот отчет об ошибках и обсуждение для получения дополнительной информации: https://code.djangoproject.com/ticket/22837

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

Если вам действительно нужен динамический выбор, лучше ForeignKey.

Альтернативным решением может быть добавление требования посредством пользовательского чистого метода для поля и/или создания пользовательской формы. Поля формы поддерживают вызываемый choices.

См. этот ответ для получения дополнительной информации: fooobar.com/questions/416289/...

Ответ 2

У меня была аналогичная проблема с настраиваемым полем, созданным для проекта Django 1.6, который имел такую ​​же общую структуру. Я пришел к следующему решению, которое работает хорошо:

class ActivePluginMeta(ModelBase):
    def __new__(cls, name, bases, attrs):
        # Override choices attr
        cls = models.base.ModelBase.__new__(cls, name, bases, attrs)
        setattr(cls._meta.get_field('plugin_name'), 'choices', cls.plugin_name_choices)
        return cls

class ActivePlugin(models.Model, metaclass=ActivePluginMeta):
    plugin_name_choices = get_active_plugins()
    plugin_name = models.CharField(max_length=32, choices=[])

Это для python 3, для python 2 вы должны указать метакласс следующим образом:

class ActivePlugin(models.Model):
    __metaclass__ = ActivePluginMeta

    plugin_name_choices = get_active_plugins()
    plugin_name = models.CharField(max_length=32, choices=[])