I have an application which is in BETA mode. The model of this app has some classes with an explicit primary_key. As a consequence Django use the fields and doesn\'t create
To change primary key with south you can use south.db.create_primary_key command in datamigration. To change your custom CharField pk to standard AutoField you should do:
1) create new field in your model
class MyModel(Model):
id = models.AutoField(null=True)
1.1) if you have a foreign key in some other model to this model, create new fake fk field on these model too (use IntegerField, it will then be converted)
class MyRelatedModel(Model):
fake_fk = models.IntegerField(null=True)
2) create automatic south migration and migrate:
./manage.py schemamigration --auto
./manage.py migrate
3) create new datamigration
./manage.py datamigration fill_id
in tis datamigration fill these new id and fk fields with numbers (just enumerate them)
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) in your models set primary_key=True on your new pk field
id = models.AutoField(primary_key=True)
5) delete old primary key field (if it is not needed) create auto migration and migrate.
5.1) if you have foreign keys - delete old foreign key fields too (migrate)
6) Last step - restore fireign key relations. Create real fk field again, and delete your fake_fk field, create auto migration BUT DO NOT MIGRATE(!) - you need to modify created auto migration: instead of creating new fk and deleting fake_fk - rename column 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')
so previously filled fake_fk becomes a column, that contain actual relation data, and it does not get lost after all the steps above.