Django makemigrations does not create models by order in models.py - django

I have a question about the order in which tables are created in a migration. As there is a ForeignKey in model B to connect to model A, I create models with order of A, B and C in models.py. Then:
python manage.py makemigrations app
There is the migration file generated to create all the models, but the order is:
- Create model B
- Create model C
- Create model A
- Add field a_name to b.
As the order in models.py really matters, but why doesn't makemigrations follow the given order?

The order in which you place your models in your models.py matters if and only if one of them references another as a ForeignKey. In such a situation the order is important and you will find the the migration does preserve the order.
What's really important is not what shows up when you do manage.py makemigrations but what happens when you do manage.py migrate there django usually figures out the correct order. If at anytime you feel that you want to control the order in which tables are created, you are free to edit the migration file (even though this is not really needed)

Related

Initial migrations after cloning repo - "related model cannot be resolved"

I'm working with a few people on an app. I'm doing front end.
Recently, I've messed up migrations. After trying to fix them for a few hours, I've dropped all tables, and cloned the repo again.
Since there are no migrations files, I run manage.py makemigrations (for some reason it does not detect all apps, just one of them, and I have to call makemigrations manually for each of them).
Then, I run manage.py migrate. I get the following error:
Related model 'User.user' cannot be resolved
Since User table has OneToOneField relation to User table. Also, other tables depend on each other as well.
My take on this problem would be commening out all the fields that cause the problem, making migrations, uncommenting them, and making migrations again.
How should I fix it?
Ok, I solved this particular problem:
In User app there was another model, which referred to User. Automatically created migration file had this model before User model, so the script failed, since it could not refer to a model that is yet not created.
I solved this by editing the migration file, swapping the order of creating models - so the second model can refer to the first one.

How to make the initial migration for a DB that diverged from the corresponding models?

Situation: a project I'm working in had a file corruption or something. Models are the latest version, but the SQLite DB had to be rolled back before some columns were added/removed/modified. Migration files are all gone. Trying to create migrations anew results in the new columns being present in the initial migration file, so I can neither migrate for real (due to the table existing) nor fake it (since the columns are missing in the DB).
Given those circumstances, how can I make an initial migration matching the columns currently present in the DB so I can fake it and then make a real second migration to bring the tables in line with the models? The only thing that comes to mind is manually tweaking the models to match the DB schema, making the initial migration, faking it and then restoring the new version of the models, but I'd much prefer having this done automatically.
django inpsectdb to the rescue.
But first, learn how to use git if you had used proper version control, you would not be facing this difficulty now.
First step, add the code to version control.
Delete the existing models files
Use inspectdb to generate a models.py from the tables in the database. This is not perfect, you will have to edit the file manually and you may have to spread it out between different models files manually.
Now delete the contents of the migrations table
do a ./manage.py makemigrations (yourapp)
Do the fake migration you mentioned
replace the generated models.py with your current models.py (a git checkout of that file will do the trick nicely)
do a makemigrations and migrate again.
good luck.

Django: Removing unique constraint and creating migration

I have created a model and migrated in Django, with a unique key constraint for one of the field. Now am trying to remove the unique constraint and generate another migration file with the new change, but it says "Nothing seems to have changed".
I tried with the command
python manage.py schemamigration --auto
PS: I am using OnetoOne relationship for the field.
Good question. A one to one relationship implies that one record is associated with another record uniquely. Even though the unique constraint is removed(for one to one field) in the code explicitly, it won't be reflected in your DB. So it won't create any migration file.
If you try the same thing for foreign constraint, it will work.
I find the django automigration file generation problematic and incomplete.
Actually I experienced another similar problem with django migration just yesterday.
How I solved it:
delete all migration files from the /migrations folder
do a fresh makemigrations
run python manage.py migrate --fake so django does not try to rebuild..
Hey presto! Working and models updated :D

Django: "column <whatever> does not exist" while running a data migration

Say I have these migrations:
0001_initial
0002_add_some_column
0003_some_data_migration
All is fine at that point, but if I add one more schema migration:
0004_add_bar_column
and then try to run the migrations against a new DB, or any DB that doesn't have 0003 yet, 0003 will bork out because "column bar does not exist".
What is the correct way to handle that scenario? Do data migrations always have to be re-done, when a schema migration is added, such that the data migrations always come last? Is there a way to make the data migration not care that "bar" doesn't exist yet? The data migration doesn't make use of "bar", but for some reason Django still thinks it needs it to exist at that point...
I'm using the build-in Django migrations, not South.
How are you accessing the models in the data migration?
Make sure you access the ORM through the apps / schema_editor rather than importing models directly.
The first argument passed to your migration worker function is an app registry that has the historical versions of all your models loaded into it to match where in your history the migration sits.
i.e. in your data migration you should not have a line this:
from my_app import MyModel
but rather, something more like this
MyModel = apps.get_model("my_app", "MyModel")

How to drop a single model in Django, and leave the others

I have 4 models. I want to redo 1 one of them that I've been working on. The other 3 models have user data that I don't want to lose.
I want to entirely drop one table, and sync it up with what's in models.py.
How do I do this?
You could remove the model from models.py, and create a migration which will drop the table.
./manage.py makemigrations
Then add the model back to your models.py, and create a new migration which will recreate the model.
./manage.py makemigrations
Finally, run your migrations and you should be done.
./manage.py migrate
It's not very clear what you want to do here.
You can write new model class and delete old model class that you want to remove. After that run migrations the normal way.
It will delete the table related to deleted model class and make whatever othe changes you have defined in the models.