如果字段的选择列表发生变化,则停止 Django 创建迁移

Stop Django from creating migrations if the list of choices of a field changes

我有一个名为 "foocore" 的 django 核心应用程序。

有几个可选的类似插件的应用程序。例如 "superfoo".

在我的例子中,每个插件都在属于 "foocore" 的模型 CharField 中添加了一个新选择。

如果选项列表发生变化,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 试图创建无用的迁移....

有办法解决这个问题吗?

查看此错误报告和讨论以获取更多信息:https://code.djangoproject.com/ticket/22837

建议的解决方案是使用可调用对象作为选择的参数,但似乎尚未针对字段执行此操作,而仅针对表单执行。

如果您确实需要动态选择,那么 ForeignKey 是最佳解决方案。

另一种解决方案是通过字段的自定义清理方法添加要求 and/or 创建自定义表单。表单字段确实支持可调用 choices.

查看此答案了解更多信息:

我为具有相同总体结构的 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=[])

我遇到了类似的问题。我的选择是动态的(从起点到现在的所有年份)并且每年第一次 makemigrations 是 运行 它都会为新选择产生新的迁移。我找到的解决方案是自定义字段,因此 choices 更改不会被 makemigrations:

检测到
from django.db import models


class YearField(models.IntegerField):

    description = "A year from 2015 to the present"

    def deconstruct(self):
        name, path, args, kwargs = super(YearField, self).deconstruct()
        # Ignore choice changes when generating migrations
        kwargs.pop('choices', None)
        return (name, path, args, kwargs)