在Django+;南方
我使用Django和South作为我的数据库。现在我想在现有模型中添加一个新模型和一个字段,并引用新模型。例如:在Django+;南方,django,django-south,Django,Django South,我使用Django和South作为我的数据库。现在我想在现有模型中添加一个新模型和一个字段,并引用新模型。例如: class NewModel(models.Model): # a new model # ... class ExistingModel(models.Model): # ... existing fields new_field = models.ForeignKey(NewModel) # adding this now 现在,Sout
class NewModel(models.Model):
# a new model
# ...
class ExistingModel(models.Model):
# ... existing fields
new_field = models.ForeignKey(NewModel) # adding this now
现在,South显然抱怨我添加了一个非空字段,并要求我输入一个一次性值。但我真正想要的是为每个现有的
现有模型
实例创建一个新的新模型
实例,从而满足数据库需求。这可能吗?在这种情况下,您需要数据迁移来补充模式迁移
South有一个很好的关于如何在文档中实现这一点的分步教程
在南方,期望的结果在两到三次架构/数据迁移中传播并不少见,因为不可能一次成功就完成(如果底层数据库允许添加非空列而没有默认值,则有时取决于底层数据库)。因此,在这种情况下,您可以添加一个具有默认值的模式迁移,然后添加一个带有对象操作的数据迁移,然后添加一个最终的模式迁移。最简单的方法是编写一个使列发生更改的模式迁移,然后编写一个数据迁移以正确填充值。根据您使用的数据库,您必须以稍微不同的方式执行此操作 Sqlite 对于Sqlite,您可以为关系添加sentinel值,并使用数据迁移来填充它,而不会出现任何问题:
0001\u schema\u migration\u将\u exforeign\u key\u从\u existing\u model.py添加到\u new\u model\u
from south.db import db
from south.v2 import SchemaMigration
from django.db import models
class Migration(SchemaMigration):
def forwards(self, orm):
db.add_column('existing_model_table', 'new_model',
self.gf('django.db.models.fields.related.ForeignKey')(default=0, to=orm['appname.new_model']), keep_default=False)
from south.db import db
from south.v2 import SchemaMigration
from django.db import models
class Migration(SchemaMigration):
def forwards(self, orm):
id = 0
if not db.dry_run:
new_model = orm['appname.new_model'].objects.all()[0]
if new_model:
id = new_model.id
db.add_column('existing_model_table', 'new_model',
self.gf('django.db.models.fields.related.ForeignKey')(default=id, to=orm['appname.new_model']), keep_default=False)
新型号.py的数据迁移
class Migration(DataMigration):
def forwards(self, orm):
for m in orm['appname.existing_model'].objects.all():
m.new_model = #custom criteria here
m.save()
这将很好地工作,没有问题
Postgres与MySQL
对于MySql,您必须给它一个有效的默认值。如果0
实际上不是一个有效的外键,您将收到错误提示
您可以将默认值设置为1,但在某些情况下,该外键不是有效的外键(发生在我身上,因为我们有不同的环境,有些环境发布到其他数据库,所以ID很少匹配(我们使用UUID进行跨数据库标识,这是上帝的意图)
第二个问题是South和MySQL不能很好地配合,部分原因是MySQL没有DDL事务的概念
为了避免不可避免地遇到的一些问题(包括我上面提到的错误和来自南方的错误,要求您将SchemaMigration中的orm
项标记为no dry run
),您需要更改上述0001
脚本以执行以下操作:
0001\u schema\u migration\u将\u exforeign\u key\u从\u existing\u model.py添加到\u new\u model\u
from south.db import db
from south.v2 import SchemaMigration
from django.db import models
class Migration(SchemaMigration):
def forwards(self, orm):
db.add_column('existing_model_table', 'new_model',
self.gf('django.db.models.fields.related.ForeignKey')(default=0, to=orm['appname.new_model']), keep_default=False)
from south.db import db
from south.v2 import SchemaMigration
from django.db import models
class Migration(SchemaMigration):
def forwards(self, orm):
id = 0
if not db.dry_run:
new_model = orm['appname.new_model'].objects.all()[0]
if new_model:
id = new_model.id
db.add_column('existing_model_table', 'new_model',
self.gf('django.db.models.fields.related.ForeignKey')(default=id, to=orm['appname.new_model']), keep_default=False)
然后,您可以正常运行新模型.py的0002\u data\u migration\u文件
我建议对Postgres和MySql使用上述相同的示例。我不记得第一个示例中的Postgres有任何问题,但我确信第二个示例对这两个示例都有效(已测试).最好将示例包含在您的答案中,而不是仅链接到它。如果该链接移动、消失或不可用,您的答案将毫无帮助。