What Is the Best Approach to Change Primary Keys in an Existing Django App

What is the best approach to change primary keys in an existing Django app?

Agreed, your model is probably wrong.

The formal primary key should always be a surrogate key. Never anything else. [Strong words. Been database designer since the 1980's. Important lessoned learned is this: everything is changeable, even when the users swear on their mothers' graves that the value cannot be changed is is truly a natural key that can be taken as primary. It isn't primary. Only surrogates can be primary.]

You're doing open-heart surgery. Don't mess with schema migration. You're replacing the schema.

  1. Unload your data into JSON files. Use Django's own internal django-admin.py tools for this. You should create one unload file for each that will be changing and each table that depends on a key which is being created. Separate files make this slightly easier to do.

  2. Drop the tables which you are going to change from the old schema.

    Tables which depend on these tables will have their FK's changed; you can either
    update the rows in place or -- it might be simpler -- to delete and reinsert
    these rows, also.

  3. Create the new schema. This will only create the tables which are changing.

  4. Write scripts to read and reload the data with the new keys. These are short and very similar. Each script will use json.load() to read objects from the source file; you will then create your schema objects from the JSON tuple-line objects that were built for you. You can then insert them into the database.

    You have two cases.

    • 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.

Alternative.

  1. Rename all your old tables.

  2. Create the entire new schema.

  3. Write SQL to migrate all the data from old schema to new schema. This will have to cleverly reassign keys as it goes.

  4. Drop the renamed old tables.

 

How to migrate from custom primary key to default id

This situation is hard to tackle particularly on sqlite which actuall doesn't even have a real ALTER TABLE statement

SQLite supports a limited subset of ALTER TABLE. The ALTER TABLE
command in SQLite allows the user to rename a table or to add a new
column to an existing table.

Most of the type, django is doing the changes via a temp table. So you can do that too

Step 1: Create a new model, exactly like

class TempModel(models.Model):
email = models.EmailField(max_length=255)
# other fields from your existing model

Note that you don't need to explicitly declare a primary key field. Merely switching it off in the email field is sufficient.

Step 2: make migrations and migrate

Step 3: open your favourite database client and do a:

INSERT INTO myapp_tempmodel(fields,....) SELECT * FROM myapp_oldmodel

Step 4: delete old table, make migrations and migrate

Step 5: rename temp table, make migrations and migrate

Update primary key Django MySQL

I don't think Django allows you to change the object's primary key. You may have to delete the original object.

e2.delete()

According to the Django docs

The primary key field is read-only. If you change the value of the primary key on an existing object and then save it, a new object will be created alongside the old one.

Django Docs

Change Primary Key field to unique field

This isn't a foolproof guide, but hopefully it will point you in the right direction.

When you add the id field, use an AutoField instead of an IntegerField. The AutoField takes care of incrementing when you add new objects.

Once the field has been created and populated, you can set primary_key=True, and remove it from your student_id.

Eventually, you should be able to remove the explicit id field from your model, since Django automatically creates one if you don't set a primary key manually.

Rename a field which was Primary Key in models.py

You modify the field to:

class MyModel(models.Model):
# …,
id = models.AutoField(primary_key=True, db_column='emp_id')
# …

If you then run manage.py makemigrations, Django will ask if you renamed the fied:

Did you rename mymodel.emp_id to mymodel.id (a AutoField)? [y/N]

a question you answer with yes.

This will still use the emp_id as the database id. If you want to rename the database column as well, you can just remove the emp_id field, and Django will use the default id field as primary key instead, and you can let Django make migrations the same way.



Related Topics



Leave a reply



Submit