How to add new field in model after custom migration which access model before new field?
I have custom migration file which creates entry in table user.
Initial working project has these migrations:
1. 001_initial.py # creates model with some fields 2. 002_custom_user_data.py # adds data in "user" due some middle requirement after some time.
Now I want to add one more column to this table as "config_data".
For this I have followed below steps:
1. python manage.py makemigrations <app-name> # creates one more migration file` 003_add_config_data_field.py 2. python manage.py migrate # raise an error
migrate command raises below error.
Applying my_user.001_initial.py... OK Applying my_user.002_custom_user_data.py ...Traceback (most recent call last): File "/home/myhome/.local/share/virtualenvs/myproject/lib/python3.9/site-packages/django/db/backends/utils.py", line 84, in _execute return self.cursor.execute(sql, params) psycopg2.errors.UndefinedColumn: column my_user.config_data does not exist LINE 1: ..., "my_user"."address",
This is because migration 002 tries to access my_user table before the add field migration(003) is migrated in the table, which is raising
UndefinedColumn config_data error.
Any idea how can be this resolved as these migrations should work for fresh DB as well as production dB in which till 002 is migrated earlier.
Below is the migration for 002_custom_user_data.py
# Generated by Django 3.2.2 from django.db import migrations from myapp.models import MyUser def create_user(apps, schema_editor): user = MyUser.objects.get_or_create(id=123) user.address = 'demo' user.save() def delete_user(apps, schema_editor): MyUser.objects.filter(id=123).delete() class Migration(migrations.Migration): dependencies = [ ('my_user', '001_initial'), ] operations = [ migrations.RunPython(create_user, delete_user, elidable=True) ]
You should import the historical model, not your current model. Django keeps track how the model looks like before you run that migration, you can access such model with the
apps.get_model(…) method [Django-doc]:
from django.db import migrations # No import from myapp.models! def create_user(apps, schema_editor): MyUser = apps.get_model('my_user', 'MyUser') user = MyUser.objects.get_or_create(id=123) user.address = 'demo' user.save() def delete_user(apps, schema_editor): MyUser = apps.get_model('my_user', 'MyUser') MyUser.objects.filter(id=123).delete() class Migration(migrations.Migration): dependencies = [ ('my_user', '001_initial'), ]
MyUser model that we thus here use will not per se have all fields of the one you define in
models.py, nor will the fields per se have the same type. You thus can here work with the model like it was at that point in time, and thus define data migrations. The records will than later be updated if you made an extra field for example.
Answered By – Willem Van Onsem