【发布时间】:2016-06-30 07:29:53
【问题描述】:
我正在尝试创建一个可调用的默认字段,如下所示:
from datetime import date, timedelta
from django.db import models
class Preferences(models.Model):
expiration_days = models.IntegerField(default=30)
... other db settings here ...
class ImportantBusinessObject(models.Model):
expiration_date = models.DateField(default=get_default_expiration_date)
def get_default_expiration_date():
expiration_days = Preferences.objects.first().expiration_days
return date.today() + timedelta(days=expiration_days)
这个想法是在数据库中存储了一组全局首选项,这些首选项会影响其他模型对象的默认值。
在向Preferences 类添加另一个字段之前,一切都很好。然后,在构建数据库时(例如,在运行测试时),添加 expiration_date 字段的迁移最终会在添加另一个首选项字段的新迁移之前执行。在调用get_default_expiration_date() 期间,Preferences 对象是最新版本,但数据库尚未获得最新迁移,我收到column preferences.new_preference does not exist 错误。
解决这个问题的最佳方法是什么?
现在我正在测试期间禁用迁移作为一种解决方法,但我想知道是否还有其他方法。
我尝试从get_default_expiration_date() 中的应用注册表中获取模型,但它仍然是最新的,而不是您在migrations.RunPython 函数中提供的版本。
我还尝试将获取 Preferences 对象的行包装在 try/except 块中,但数据库最终处于回滚状态,我无法继续。
其他位:
- 我使用的是 Django 1.8
- 在我的实际应用中,
Preferences类实际上是使用 django-solo 的 db 单例。
UPDATE:明确操作顺序
以下是正在发生的事情的时间表:
-
preferences/migrations/initial_0001.py:初始偏好,包括expiration_days -
business/migrations/initial_0001.py:初始业务对象,依赖于preferences 0001 -
preferences/migrations/add_pref_0002.py:给Preferences添加一个新字段
一旦我在第 3 步中定义了迁移,事情就开始中断,因为在运行以从第 2 步添加迁移时,会调用get_default_expiration_date,这会引发错误。从下面关于更新依赖项的评论线程中,我的观点是,为了做到这一点,每次我添加新的首选项迁移时,我都需要更新先前定义的 business/migrations/initial_0001.py 的依赖项(以及任何其他行为类似的)。希望这可以稍微澄清一下情况。
【问题讨论】:
-
您是否尝试过编辑dependencies 以便首先运行
Preferences迁移? -
我没试过。编辑以前创建的迁移的依赖项以依赖于新的依赖项感觉很奇怪(然后每次我向
Preferences添加新迁移时都必须手动管理依赖项。)不过,这可能是另一种解决方法。 -
我对两次迁移之间运行的代码感到困惑。运行测试时,它应该通过在执行任何测试代码之前运行所有迁移来重建数据库。您是否有正在为现有对象设置新首选项的数据迁移?
-
更新问题试图澄清
标签: python django django-models django-migrations