I have a model which inherit from a non-abstract super model:
class Person(models.Model):
pass
class User(Person):
pass
Because of a conception mistake we want to remove the Person model and copy all person data to users. The main problem concern the "id" AutoField.
The user model doesn't have any id field autocreated by django. Because of inheritance the user's primary key is "person_ptr_id".
I'm trying to make database migrations. Django migrations want to add the "id" field as AutoField but ask for a default value. I want the initial value copied from the person_ptr_id for each user record. I also want the postgres sequence synced with values.
Have you already performed such migrations ?
I finally succeed doing it with theses migrations :
1) Change django's automatic migration by commenting column deletion of person_ptr and column creation of 'id'. Then add an 'id' column as integer :
migrations.AddField(
model_name='user',
name='id',
field=models.IntegerField(null=True)
),
2) Create a new empty migration for migrating data from person to user, removing person_ptr field and change 'id' type to AutoField
def copy_persons_data(apps, schema_editor):
User = apps.get_model("accounts", "User")
Person = apps.get_model("persons", "Person")
for user in User.objects.all():
person = Person.objects.get(id=user.person_ptr_id)
user.new_field1 = person.new_field1
user.new_field2 = person.new_field2
user.id = person.id
user.save()
class Migration(migrations.Migration):
dependencies = [
('accounts', '0026_auto_20170606_1524'),
]
operations = [
migrations.RunPython(copy_persons_data, reverse_code=migrations.RunPython.noop),
migrations.RemoveField(
model_name='user',
name='person_ptr',
),
migrations.AlterField(
model_name='user',
name='id',
field=models.AutoField(auto_created=True, null=False, primary_key=True, serialize=False, verbose_name='ID'),
preserve_default=False,
),
]
Doing this, django will automatically create sequence for 'id' field synced with max id.
Notes :
Using user.person_ptr in datamigration function will make django refuse to save user because of unsaved person instance. So I do a get query to fetch user's person instance.
perserve_default=false is important to avoid django need a new migrations for removing the default value for the autofield