我有一个应用程序,这是在测试模式。这个应用程序的模型有一些带有显式primary_key的类。因此,Django使用字段,并且不会自动创建id。
class Something(models.Model):
name = models.CharField(max_length=64, primary_key=True)我认为这是一个糟糕的想法(参见unicode error when saving an object in django admin),我想搬回去,为我的模型的每个类都有一个id。
class Something(models.Model):
name = models.CharField(max_length=64, db_index=True)我已经对模型进行了更改(将每个primary_key=True替换为db_index=True),并希望使用south迁移数据库。
不幸的是,迁移失败,并显示以下消息:ValueError: You cannot add a null=False column without a default value.
我正在评估这个问题的不同解决方法。有什么建议吗?
谢谢你的帮忙
发布于 2010-01-13 19:11:43
同意,你的模型可能是错的。
正式主键应该始终是代理键。再也不会有别的事了。很有说服力。重要的经验教训是:一切都是可变的,即使用户以他们母亲的坟墓发誓,值是不能改变的,这真的是一个可以作为主要的自然关键字。它不是主要的。只有代理可以是主要的。
你在做心内直视手术。不要搞乱模式迁移。您正在替换架构。
依赖于这些表的表将更改其FK;您可以就地更新这些行,或者也可以删除并重新插入这些行--这可能会更简单。
json.load()从源文件中读取对象;然后,您将从为您构建的JSON tuple-line对象创建您的模式对象。然后您可以将它们插入到数据库中。你有两个案子。
- Tables with PK's change changed will be inserted and will get new PK's. These must be "cascaded" to other tables to assure that the other table's FK's get changed also.
- Tables with FK's that change will have to locate the row in the foreign table and update their FK reference.
另类选择。
SQL将所有旧模式重命名为整个新的schema.
发布于 2012-04-21 01:42:38
要将主键更改为south,您可以在数据迁移中使用south.db.create_primary_key命令。要将您的自定义CharField pk更改为标准AutoField,您应该执行以下操作:
1)在模型中创建新字段
class MyModel(Model):
id = models.AutoField(null=True)1.1)如果你在这个模型的其他模型中有一个外键,也在这些模型上创建新的伪fk字段(使用IntegerField,然后它将被转换)
class MyRelatedModel(Model):
fake_fk = models.IntegerField(null=True)2)创建自动南迁和迁移:
./manage.py schemamigration --auto
./manage.py migrate3)创建新的数据迁移
./manage.py datamigration <your_appname> fill_id在数据迁移中,用数字填充这些新的id和fk字段(只需枚举它们)
for n, obj in enumerate(orm.MyModel.objects.all()):
obj.id = n
# update objects with foreign keys
obj.myrelatedmodel_set.all().update(fake_fk = n)
obj.save()
db.delete_primary_key('my_app_mymodel')
db.create_primary_key('my_app_mymodel', ['id'])4)在您的模型中,在新的pk字段上设置primary_key=True
id = models.AutoField(primary_key=True)5)删除旧的主键字段(如果不需要),创建自动迁移并迁移。
5.1)如果您有外键-也删除旧的外键字段(迁移)
6)最后一步-恢复fireign键关系。再次创建真实fk字段,并删除您的fake_fk字段,创建自动迁移但不迁移(!)-您需要修改已创建的自动迁移:而不是创建新的fk并删除fake_fk - rename列fake_fk
# in your models
class MyRelatedModel(Model):
# delete fake_fk
# fake_fk = models.InegerField(null=True)
# create real fk
mymodel = models.FoeignKey('MyModel', null=True)
# in migration
def forwards(self, orm):
# left this without change - create fk field
db.add_column('my_app_myrelatedmodel', 'mymodel',
self.gf('django.db.models.fields.related.ForeignKey')(default=1, related_name='lots', to=orm['my_app.MyModel']),keep_default=False)
# remove fk column and rename fake_fk
db.delete_column('my_app_myrelatedmodel', 'mymodel_id')
db.rename_column('my_app_myrelatedmodel', 'fake_fk', 'mymodel_id')因此,以前填充的fake_fk变成了一个包含实际关系数据的列,并且在完成上述所有步骤后,它不会丢失。
发布于 2017-10-02 06:00:31
我使用django 1.10.4迁移和MySQL5.5成功做到了这一点,但这并不容易。
我有一个带有几个外键的varchar主键。我添加了一个id字段、迁移数据和外键。这是如何实现的:
id = models.IntegerField(default=0)字段,并生成了一个自动migration.def fill_ids(app,schema_editor):模型= apps.get_model('','')表示id,枚举中的代码(Model.objects.all()):code.id = id +1 code.save()类迁移(migrations.Migration):dependencies =…操作= migrations.RunPython(fill_ids)
def change_model_fks(app,schema_editor):apps.get_model= FkModel (‘’,'') #我们想要将模型的主键改为apps.get_model= apps.get_model('','') #通过外键映射引用第一个的其他模型= {}对于Model.objects.all()中的模型: mappingmodel.old_pk_field = model.id #对于FkModel.objects.all()中的fk_model,将旧的主键映射为新的:如果fk_model.model_id: fk_model.model_id = mappingfk_model.model_id #更改引用fk_model.save()类迁移(migrations.Migration):依赖关系=…操作=#删除外键约束migrations.AlterField( model_name='',name='model',field=models.ForeignKey('',blank=True,null=True,db_constraint=False) ),#更改引用名称(Change_model_fks),#将字段从varchar更改为整数,删除索引migrations.AlterField( model_name='',name='model',field=models.IntegerField('',blank=True,null=True) ),
primary_key=True,b)删除了id字段时,我自动生成了这次迁移的基础类迁移(migrations.Migration):依赖关系=…操作=[# Drop old primary key migrations.AlterField( model_name='',name=‘’,field=models.CharField(max_length=100),),# Create new PRIMARY KEY migrations.RunSQL( 'ALTER TABLE CHANGE id INT (11) NOT NULL primary key AUTO_INCREMENT','ALTER TABLE CHANGE id INT (11) NULL','ALTER TABLE DROP PRIMARY KEY',state_operations=migrations.AlterField( model_name='',name=' id ',field=models.AutoField(auto_created=True,primary_key=True,serialize=False,verbose_name='ID'),) ),#重新创建外键约束migrations.AlterField( model_name='',name='model',field=models.ForeignKey(blank=True,null=True,to=‘.),]
https://stackoverflow.com/questions/2055784
复制相似问题