在我的Django模型中,我有两个字段,name
(一个常规的CharField
)和slug
,这是一个自定义字段,根据字段定义中传递的字段名生成段塞,在这种情况下,我使用name
。
首先,该模型只有name
字段,以及相应的迁移等等。然后我需要添加slug
字段,所以按照South的约定,我用unique=False
添加了slug字段,创建了模式迁移,然后创建了数据迁移,设置了unique=True
,并为最后的更改创建了另一个迁移。
由于slug的值是在模型保存时生成的,所以在数据迁移的forwards
方法中,我所做的是迭代orm['myapp.MyModel'].objects.all()
返回的查询集,并在每个实例上调用save()
方法。
但是,段塞场的值永远不会生成。在一个IPython会话下,我做了同样的事情,但将模型引用为from myapp.models import MyModel
,并成功了。使用一些调试语句,打印South的orm dict返回的模型的type
显示了真实的类,它似乎不是South动态构建的伪模型。
当使用pre_save
方法时,段塞字段会创建它的值。如何在数据迁移过程中强制调用它?我需要确保值的唯一性,以便在以后的架构迁移中应用索引时,列不会包含重复的值。
谢谢!
顺便说一句:slug字段类确实定义了south_field_triple
,所以South玩得很好。
编辑:请看我的答案。但更像是一个答案,感觉更像是黑客。有更好/正确的方法吗?
通常,您应该在迁移中尽可能紧密地显式复制生成字段内容的代码(这是一个罕见的有目的的代码复制示例)。方法中的代码,即使有效,也会调用执行迁移时定义的pre_save,这可能与创建迁移时的模型状态发生了变化,甚至失败(这可能取决于以前不存在的其他字段等)
因此,在您的示例中,正确的方法是直接使用slugify(),就像在SlugField的pre_save方法中所做的那样:
from django.template.defaultfilters import slugify
class Migration(DataMigration):
def forwards(self, orm):
"Write your forwards methods here."
for myobj in orm['myapp.MyModel'].objects.all():
myobj.slug = slugify(myobj.otherfield)
myobj.save()
我通过获得模型字段实例并直接调用它的pre_save
来暂时解决这个问题:
class Migration(DataMigration):
def forwards(self, orm):
"Write your forwards methods here."
# Note: Remember to use orm['appname.ModelName'] rather than "from appname.models..."
for myobj in orm['myapp.MyModel'].objects.all():
slug_field = myobj._meta.get_field_by_name('slug')[0]
myobj.slug = slug_field.pre_save(myobj, add=False)
myobj.save()
然而,在自定义字段中考虑这一点会让人觉得很麻烦。。。