如果字段的选择列表发生变化,则停止 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)
我有一个名为 "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)