Django: When to run makemigrations? - django

In addition to adding/deleting/modifying field to model, Django also detects changes when I add or modify methods to the model.
So my question is should I run makemigrations every time I change or add a new method in models ?

When you add/change model methods, then you don't need to run ./manage makemigrations and ./manage.py migrate.
But whenever you edit your model fields (adding a new one, changing an existing one or altering any of the arguments it takes) then you should always run migrations.

First of all,
./manage makemigrations
will create (migration_number).py files in your app migrations folders. These lines of code are nothing but statements which help in creating actual fields in your respective database similar to SQL statements.
In order to execute the migration which was created using the previous command, we will run the following command,
./manage.py migrate
On migrate your new model fields will be reflected in database if there are no errors

Related

Operational Error no such column in Django 3.0

I changed the name of the attributes of one of my models. As soon as I made the change in the models.py script, I tried to migrate it using makemigrations command, but it kept giving me an error that the email field is non-nullable and the database needs something to populate the existing rows. So I tried to reverse the previous migrations and ran the command python3 manage.py <app_name> zero.
After this the previous non-nullable field error was resolved at the command line but as soon as I submit the form at the browser, I run into this Operational error.
The crux of the matter is how to make changes to the attributes of one of the models in models.py and deal with the consequent migrations ?
You might want to delete your database or running the python manage.py flush commands when making such changes. If you do not want to do that, just add a one-time default (make sure its the right type).

Django - wont let me add a new field to my model because 1054, "Unknown column 'field list'")

I am trying to simply add a boolean field to a model in my database following the simple rules:
- add field to model
- python manage.py makemigrations app
- python manage.py migrate app
Works all but 99% of the time. So during the second step (makemigrations), with my newly added field in my model raring to go, i get an error:
django.db.utils.OperationalError: (1054, "Unknown column 'model.field' in 'field list'")
Excellent. its not letting me make migrations by adding a new field..... because it cant find the field that I am trying to newly add... makes perfect sense!
Anyway, I have gone as far as deleting all my migrations, removing my new field, making migrations again, migrating... all fine - so now i have only 1 migration file (0001)...
Follow the same steps as above... ERROR
Am i missing something ridiculous here? I mean, adding a field to a model is very simple, and I have done it probably 1000 times. Why does Django tease me so
EDIT: Answer:
OK I have done it.
After deleting the migrations file, truncating the migrations table and migrating with 0001_initial.py, I made an empty migrations file (python manage.py makemigrations --empty app) and added the field in manually.... then I migrated and it worked! Baffled at this to be honest, but at least the change has been made:
Delete all migration files
Truncate the django_migrations table
comment the new boolean field
run python manage.py makemigrations
run python manage.py migrate --fake
run python manage.py makemigrations --empty app
add field in manually to the empty migrations file in the operations:
migrations.AddField('modelName', 'fieldName', models.BooleanField(default=False)),
run python manage.py migrate
uncomment the new boolean field so it represents what you made in the migrations operations
Disclaimer- Follow this only on local system, for production do understand the steps and then execute.
Kindly follow these steps:
Delete all migration files
Truncate the django_migrations table
comment the new boolean field
run python manage.py makemigrations
run python manage.py migrate --fake
Uncomment the boolean field
run python manage.py makemigrations
run python manage.py migrate
Generally these steps solve any kind of migration problem
An another reason can be if you are using django_rest_framework then the serialiser too needs to be updated as per your model change.
This is an issue that has persisted with me and lead me down a lot of rabbit holes dropping tables etc. A simple solution I have found is answering "N" when django asks you if you are renaming a field of that model (when running makemigrations). What that then essentially performs is a deletion of your previous field and creates the new field. Be careful as you may lose data on existing field so this works with fields which are either new or relatively easy to 'refill' their data required. You may need to run --fake if you get an error with regards to not being able to 'drop field' when migrating after makemigrations. If you would like to go back to your migration state before the problem you may need to delete the migrations you have done since then and try the above solution.
Update:
I did the above for a Boolean field and my data was kept. Even though I said N, it seems as if it is essentially a renaming.
Another source of the problem: I have a ModelForm based on the model. The ModelForm definition defines two extra fields. I had to comment out those two fields from the Form definition before doing the migration steps. Once the migration was done, I un-commented the two fields.

Django migrate didn’t launch execute some migration files

I have a Postgres database full of data. And I made several changes to my Django app models.
mange.py makemigrations worked fine and created the migration files. But manage.py migrate execute only one file. And when I launch it again it doesn’t execute the rest as if they are already applied.
I deleted the migration files that were not applied and did another makemigration but it says no changes detected.
Any ideas how to reflect the models changes on the database without losing the data ?
Thanks
Django keeps track of which migrations it has applied already, so when you run the migrate command it will execute only the migrations that Django thinks that are missing.
I deleted the migration files that were not applied and did another makemigration but it says no changes detected.
This was a bad idea, it will make your migrations inconsistent.
If you want to go back in time, instead of deleting migrations, the proper way to do this is by reverting migrations. You can use the same migrate command and specify to which migration point you want your database model to be.
Check this answer for further information about reverting migrations; django revert last migration

Django migrations : relation already exists

I have trouble with django model migrations.
I have some models in my app, and I already have some data inside.
When I added some models in my application, and I run makemigrations, the app report that there is no change.
I know that sometimes some errors came when migrate, so I delete django_migrations table in my database and run makemigrations again, and now program found my new fields.
The problem now is that if I run migrate system tell me that some tables already exist. (Which is ok and correct, because they do). I don't want to delete those tables, because I have data already inside.
I can't run migrate --fake, because program will think that I already have all the tables, which is not true.
So, I am looking for a way to tell the program : run migration, if table exist skip it. (--fake it)
Another question is why is this happening to me, that makemigrations don't recognise my changes (some cache problems,...)?
How about doing this way ?
python manage.py makemigrations
(Skip this step if you have already have migration file ready)
It will create migrations for that package lets say with a name like 0001_initial.py
Edit the file manually so that you delete all models there except that was already created in database.
Now you do a fake migration. This will sync your database with models.
python manage.py migrate --fake
Then run makemigrations again to have rest of the tables created along with a new migration file.
python manage.py makemigrations
Regarding your other question, Why makemigrations didn't recogonize your models can be because of reasons like:
Migrations for those changes are already there in some migration file.
You missed it to mention package_name in INSTALLED_APPS but i believe you did it here.
every time you make changes to your models, try these steps :
python manage.py makemigrations [your app name]
then:
python manage.py migrate
it should work fine. but remember if you have already data(rows) in your tables you should specify the default value for each one the queries.
if not, Django prompt you to specify the default value for them
or you can just try to use blank=True or null=True in your fields like below :
website = models.URLField(blank=True)
the possible cause or this is that you have another migration in the same folder starts with the same prefix... maybe you make another migration on the same table on another branch or commit so it's saved to the db with the same prefix ie: 00010_migration_from_commit_#10, 00010_migration_from_commit_#11
the solution for this is to rename the migration file like this 00011_migration_from_commit_#11
I tried to edit the related migration file and commented the part where it creates that specific column, then ran python manage.py migrate
The main problem is the existing tables that are disabling the migration of the new tables, so the solution is straight-forward:
** Try to add managed = False to the existing dB so it won't be detected by migrate
** Redo it for all existing old tables :
class Meta:
managed=False
It sometimes gets boring when we have a lot of tables in the same application but it works perfectly!

Django migrations for a cloned db

I cloned a postgres db and added a new model to one of the apps. Our project contains many apps.
Now When I ran migrations, migrate it would fail. So I commented that model out, deleted migrations.py file from folder and ran fake migrations. Than again put that model in and ran migrations, migrate. Things were fine.
But now I deleted this model table from db manually and when would run migrations it would show model doesn't exist.
Basically I would need to again and again tweak the model, delete, update table.
So I searched for migrating from scratch. Did delete some apps from django_migrations table. But it is not working out it shows relations already existing.
This is all becoming confusing, --fake, delete, squash what to do?
Basically if I drop table django_migrations, delete migrations folder from app. Can't django automatically sync with db and understand what model exist and what don't and figure it out itself.
If you want to create a clone of a Django database, without the data, there's one table you should always get the data from: django_migrations. This is the table that holds the state of the database: which migrations have been applied and as such what models exist already.
The fact that Django tries to create one it's core models tells me you didn't have the data from django_migrations in the clone.
This solved the problem.
deleted all the data from 'django_migrations' table.
deleted all the migrations file from all migrations folder in different apps
Commented out the models whose table are still not in database
ran python manage.py makemigrations
ran python manage.py migrate --fake
Put the comments off the model
ran python manage.py makemigrations
ran python manage.py migrate
Thing is to understand what does makemigrations and migrate does. And then you can delete/update manually or created new models and migrate/clone things etc. it would work. For a new starter these commands are little confusing.
Let's says everything is empty i.e. no files in migration folder of app.
Than makemigrations makes these files which contains say sqls/syntax on how to create your table. With each change it will create a new one, with only the changes listed in that.
migrate creates actual empty tables in the database. And creates an entry in django_migrations against the app that model was part of. This entry tells it when was the latest entries from that file were applied to the database.
Scenario 1:
I deleted one table manually from db. Now django doesn't know about it. So if you would run makemigrations or migrate it would do nothing.
Scenario 2:
I deleted all entries from django_migrations, deleted migrations files from app. Tables are still in db. Now when I do makemigrations it works, but when I migrate it throws error that already existing.
Scenario 3:
Have deleted entries from django_migrations and migration files. Django has one option of migrate --fake, this tells it that tables are already existing just make entries in django_migrations table. so makemigrations and migrate --fake works now without error. But now the table which I deleted manually is still deleted, django hadn't made it. So will throw error when I try to access it.
Scenario 4:
The one I described at start. I faked the entries which were in db and then migrated the model which wasn't in db.
So once one understands what's it's doing behind the scenes many approaches could have been followed, create the table schema manually or selectively pick django_migrations or migrations file entries and delete them. But best is to delete everything and start from scratch.
It would have been best that django understands that these are tables already created, these are models I have, create the missing one, leave the existing ones. If any discrepancy show them. I see so many questions related to migrations and people are confused here and there.