Note:
我理解并且很清楚将函数作为参数传递和调用函数并将结果作为参数传递之间的区别。我相信我正确地传递了该函数。
Specs
设想:
我的应用程序中有数十个模型,并且有许多现有记录。我需要向每个模型添加一个随机种子,这些模型将在创建新模型实例时创建和设置。我还想为现有实例生成随机种子。
我的理解如何Django 模型默认值 and 迁移工作原理是,当一个新字段添加到模型中时,如果该字段设置了默认值,Djano 将使用新字段和相应的默认值更新所有现有实例。
然而,尽管事实上我确实传递了一个函数作为默认值,并且该函数生成一个随机数,但 Django 在更新现有行时使用相同的随机数(例如,Djano 似乎只调用该函数一次,然后使用所有条目的返回值)。
Example
我的代码的缩短版本:
def get_random():
return str(random.random())
class Response(models.Model):
# various properties
random = models.CharField(max_length=40, default=get_random)
user = models.ForeignKey(User, on_delete=models.CASCADE)
content = JSONField(null=True)
随机字段是在模型之后添加的,并且它的许多实例已经创建。 Amakemigrations
命令似乎生成了正确的迁移文件,其中包含migrations.AddField()
调用、传入default=get_random
作为参数。
然而,运行后makemigrations
,所有现有的Response
实例中包含完全相同的数字random场地。创建和保存模型的新实例按预期工作(使用伪唯一随机数)。
解决方法
一种简单的解决方法是只运行一个一次性脚本,该脚本执行以下操作
for r in Response.objects.all():
r.random = get_random()
r.save()
或者覆盖模型的save()
方法,然后进行批量保存。但我认为这些解决方法没有必要。这也意味着,如果我想创建一个具有随机默认值的唯一字段,那么我将需要多次迁移。首先,我必须添加具有指定默认值的字段。接下来,我需要应用迁移并手动重新初始化字段值。然后进行第二次迁移以添加unique=True
财产。
似乎 Django 要将默认值应用于现有实例makemigrations
那么它应该使用与创建新实例相同的语义来应用它们。有没有办法强制 Django 在迁移时为每个模型实例调用该函数?