Django反复检测到冗余迁移。

11

背景

我们在 Python3.4 / Django1.8.4 上工作,并且我们目睹了关于我们的user模型,特别是该模型的timezone字段的奇怪现象。

偶尔,在我们进行迁移时,新的迁移文件会包括一个操作来更改上述时区字段,但是操作中包含的所有属性都已经设置为迁移尝试分配的相同值!

这里有3个这样的字段:

1)default - 其值为"UTC"

2)max_length - 其值为30,以及

3)choices - 一个非常长的元组数组,包含时区名称/值。

它看起来像:

choices=[('Africa/Abidjan', 'Africa/Abidjan'), ('Africa/Accra', 'Africa/Accra'), ('Africa/Addis_Ababa', 'Africa/Addis_Ababa'), ... ]

迁移操作总是想要将timezone字段的这3个属性设置为完全相同的3个对应值,即使它们已经设置为这些值!这实际上是一个多余的、无用的操作。

有时当我们运行makemigrations时,应用程序没有任何更改,除了这个愚蠢的字段!

问题

1)为什么会发生这种情况?

2)我们如何防止这种情况?很烦人,应用程序认为需要进行迁移,但实际上并不需要。

额外信息

虽然字段的相同3个属性总是被设置为完全相同的值,但它们在操作中出现的顺序似乎是不确定的(可能是因为django使用无序的dict实例来存储生成迁移文件所使用的数据)。

与我们在模型中定义的choices字段一样,它在应用程序初始运行时是动态生成的。代码看起来像这样:

class MyUser(models.Model):
    f_name = models.CharField(max_length=32398) # Gotta accomodate those crazy south-eastern names haha
    l_name = models.CharField(max_length=94823)

    # ...
    # more fields and stuff etc.
    # ...

    time_zone = models.CharField(default="UTC", choices=TIMEZONE_CHOICES, max_length=30)

重要的部分是 choices=TIMEZONE_CHOICES,它在前面被定义为:

import pytz
TIMEZONE_CHOICES = ()
for time_zone in pytz.common_timezones:
    TIMEZONE_CHOICES += ((time_zone, time_zone),)

仅在情况相关时包含此信息。


不,但是几次迁移之后可能会被检测到! - Gershom Maes
1
你确定是 pytz.common_timezones 而不是 pytz.common_timezones_set 吗?我猜测 TIMEZONE_CHOICES 在某种程度上发生了变化。尝试从迁移文件中提取 choices=[...](可能需要手动),并进行比较。 - vsd
肯定是 2015.4,但这是一个与其他开发人员合作的项目,他们可能使用更新版本的pytz 进行迁移! - Gershom Maes
为了确认您所写的内容,请在迁移文件中放置一个重置字段的摘录。 - Djizeus
好的!也许回答你的问题会对有类似问题的人有所帮助。 - Djizeus
显示剩余7条评论
3个回答

1
尝试将pytz的纯时区列表复制到您的项目中,以确保选择不依赖于第三方。

我必须说,我不确定我是否喜欢这个解决方案,因为我更喜欢跟上pytz不断发展的时区列表。我认为更好的解决方案是简单地更新pytz - Gershom Maes

1

考虑到我们在注释中找到了问题的真正原因,这是一个很好的解决方案,可以修复问题! - Gershom Maes

0

你的时区可能在不同的运行中以不同的顺序出现。请尝试

import pytz
TIMEZONE_CHOICES = ()
for time_zone in pytz.common_timezones:
    TIMEZONE_CHOICES += ((time_zone, time_zone),)
TIMEZONE_CHOICES = sorted(TIMEZONE_CHOICES) # sort list to make it consistent

另外——虽然这只在启动时运行,但是通过重复连接构建大元组可能比这更昂贵

import pytz
TIMEZONE_CHOICES = sorted((tz,tz) for tz in pytz.common_timezones)

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接