I have been assigned the task to work on project involving react UI and django backend. There are two versions of this app:
older version which runs on older versions of react and python (v2)
newer version which runs on newer versions of react and python (v3)
I have been tasked to move some functionality from older version to newer version and test it with postgres database dump from a live environment running older version. The challenge could be differences in the database schema of newer and older versions. (But, most possibly there wont be much differences if some minor ones.)
So I proceeded to take the database dump, attached it to the database running on my laptop and specified its name in my django's settings.ini. But when I started my django app, it gave me error
You have 7 unapplied migration(s). Your project may not work properly until you apply the migrations for app(s): admin, auth, lab, otherlabs. Run 'python manage.py migrate' to apply them.
When I ran python manage.py migrate, it gave me an error:
Migration abc.0001_initial is applied before its dependency auth.0011_xyz on database 'default'.
So, I deleted record corresponding to abc.0001_initial from django_migrations table and reran python manage.py migrate. Now I got same error for migration of another project def but with the same dependency auth.0011_xyz:
Migration def.0001_initial is applied before its dependency auth.0011_xyz on database 'default'.
Should I proceed with deleting record corresponding to def.0001_initial too? Am afraid that this will continue till I delete all such 0001_initial-suffixed records. There are 35 projects and hence 35 such 0001_initial-suffixed records.
Q1. Is it safe to delete them all and run the migrations? Is deleting all migrations and rerunning them really bad idea if they are schema-only migrations (we use fixtures for importing data)? Or is it simply impossible to do as most of those migrations will fail as tables corresponding to most models are already there in the database (or this wont give any error?), so the only solution remained is to delete migrations record one by one from db till I get no errors. But wont this still give error as I am only deleting migrations record and not actual tables created by migrations? Is there any other approach?
Q2. Are migrations completely safe to "re"-run? I mean if one fails because corresponding table / columns are already there or for some other reasons, will it leave database in consistent state or will it mess up the database?
Q3. Also will it continue to execute rest of the migrations after one fails? OR
Q4. Can / should I execute rest of the migrations if one fails? If yes, do I need to pass some arguments to python manage.py migrate or its default behavior?
Update
I tried removing all migrations from the django_migrations table. And then running python manage.py makemigrations followed by python manage.py migrate. But migration did not complete and terminated with error "relation already exist". So applied fake migration python manage.py migrate --fake. It succeeded (seems that it faked / skipped all migrations as all corresponding tables were present, so it did not create new columns in already existing tables). But then my REST API calls started failing with error in response saying: "column xyz does not exist".
Manually copying data seems impossible since there are 156 tables 🥲
Please let me know if there are any solution to this.
You need to delete the migration row from django_migrations for migration def.0001_initial, then apply migrate auth 0011_xyz to fix the dependency and then you should can to do migrate def 0001_initial --fake to fake the migration and add the row you deleted before to django_migrations.
Related
I deployed my application to Heroku, but I am not able to add any data.
When I tried to open first table with data from model I received this error message:
ProgrammingError at /category/category_table
relation "tables_category" does not exist
LINE 1: SELECT COUNT(*) AS "__count" FROM "tables_category"
And when I tried to add first data I received this error message:
ProgrammingError at /admin/tables/category/add/
relation "tables_category" does not exist
LINE 1: INSERT INTO "tables_category" ("category_name") VALUES ('sho...
I went through similar Q/A here, but they do not solve my issue, as I have:
a) deleted all migration files from my local disk, then
b) I run: python3 manage.py makemigrations
c) I run: heroku run python3 manage.py migrate
So all should be up to date and I have this log from Heroku:
Operations to perform:
Apply all migrations: admin, auth, contenttypes, sessions, tables
Running migrations:
No migrations to apply.
So currently do not know what to do.
Don't delete migrations
The first step here is very dangerous:
I have... deleted all migration files from my local disk
It is very likely that the new migrations you generate won't work on your local machine. They will attempt to migrate from an empty database to whatever your current state is, but you (presumably) already have tables and maybe even data in your local database from earlier migrations.
Deleting migrations is almost never the right answer. I know a lot of people recommend it whenever you get into migration trouble, but they are wrong. Throwing away your database might feel safe during early development, but it definitely isn't desirable when you have real data later on.
I strongly suggest that you restore your old migration files, then generate new migrations on top of them.
Generating and applying migrations
When you run
python3 manage.py makemigrations
you generate new migration files on your local machine. Heroku has no idea that they exist, so running
heroku run python3 manage.py migrate
won't do anything.
After cerating migrations on your local machine, apply them locally by running python manage.py migrate to make sure they do what they're supposed to do. When you're happy with them, commit the files, redeploy to Heroku, and then run the migrations on Heroku.
I have a table in my database (postgresql) that is associated with a model called feedback in my Django app (which is also called feedback).
I deleted a couple of columns of the feedback model in the models.py file and then created a migration using:
python manage.py makemigrations feedback
And then tried to "merge" it with my database using:
python manage.py migrate feedback
But i got the error:
django.db.utils.ProgrammingError: relation "feedback" already exists
Of course it exists, but i want to apply the changes i've made. In the migrations folder i have the following files:
__init__.py
0001_initial.py
0002_remove_feedback_created_on.py
0003_remove_feedback_is_read.py
The last one contains my most recent changes. What should i do?
Usually this relation x already exists problem appears when you've applied the change at some point in the database, but the Django migrations system hasn't got a clue about the fact that you already did that. How could it happen? For example if you add a ForeignKey field to your model, make a migration, migrate it, but then change your mind and delete the migration without migrating backwards before that. Nothing breaks in the project, but the relationship and the field in the database remain (you might run into trouble, if the field is non-nullable). Now if you change your mind again and decide that shiiit, I needed that field anyhows and add it again, make a new migration and try to migrate it, then you get the relation x already exists error.
Ok, what then? Usually the simplest way is to fake the failing migration, but BEWARE that if you have any other unapplied changes in the migrations, then those won't be applied to the database either. Before you start faking migrations, make sure that you understand what and why you are faking. Ideally you'd have only one AddField in the migration file that is soon to be faked, because otherwise all changes in the migration file will be faked (faking migrations means, that the changes are not applied to database, but Django will consider them done).
If you have two unapplied migrations, then you definitely shouldn't run migrate --fake without specifying the migration number, because then the latter unapplied migration will be unapplied as well. It SEEMS in your case, that running manage.py migrate 0002 --fake and manage.py migrate afterwards might fix everything, but without knowing everything about what you've done, it's impossible to say for certain.
If I picked up your project, here's what I would do:
1) Check if 0002 contains more than one change.
If yes, then copy everything except the failing field to 0003.
If no, then proceed to manage.py migrate 0002 --fake.
2) Run manage.py migrate again to migrate 0003.
It could also help in the case of migrations.
python3 manage.py migrate --run-syncdb
I'm trying to switch database backends for an existing django-cms project, from sqlite3 to postgresql. When I start with a fresh sqlite database and apply all migrations everything works fine. If I do the same with a fresh postgres database everything appears to go ok but I get the following error when trying to do anything:
django.db.utils.ProgrammingError: relation "cms_urlconfrevision" does not exist
LINE 1: ...sion"."id", "cms_urlconfrevision"."revision" FROM "cms_urlco...
I get a warning while running runserver that there are unapplied migrations despite the fact that a listing of migrations shows all applied, and running migrate again does nothing (makemigrations also does nothing). The cms_urlconfrevision table exists in the database, with the id and revision fields, so I'm at a loss for where to look further.
Adding versions: django 1.9.7, django-cms 3.4.4
After choosing a new database, first comment out all the other apps you have put in the INSTALLED_APPS. Then makemigration and migrate. If that works then add other apps and create migrations and migrate.
If still it doesn't work.
Try to delete all the earlier created migrations from migrations directory in every app. And then again makemigrations and migrate.
I have a Python/Django proyect. Due to some rolls back, and other mixed stuff we ended up in a kind of odd scenario.
The current scenario is like this:
DB has the correct tables
DB can't be rolled back or dropped
Code is up to date
Migrations folder is behind the DB by one or two migrations. (These migrations were applied from somewhere else and that "somewhere else" doesn't exist anymore)
I add and alter some models
I run makemigrations
New migrations are created, but it's a mix of new tables and some tables that already exist in the DB.
If I run migrate it will complain that some of the tables that I'm trying to create already exist.
What I need:
To be able to run the migrations and kind of "ignore" the existing tables and apply the new ones. Or any alternative way to achieve this.
Is that possible?
When you apply a migration, Django inserts a row in a table called django_migrations. That's the only way Django knows which migrations have been applied already and which have not. So the rows in that table have to match the files in your migrations directory. If you've lost the migration files after they were applied, or done anything else to get things out of sync, you'll have problems.. because the migration numbers in your database refer to different migration files than the ones in your project.
So before you do anything else, you need to bring things back into sync by deleting the django_migrations table rows for any migration files that you've lost somehow and can't get back. The table should contain rows for only those migrations that you do have and that were actually applied to the database correctly.
Now you need to deal with any changes in your database that Django Migrations doesn't know about.. and for that there are a few options:
If things worked out such that the database changes that were already applied to the database are in different migration files than the ones that weren't, then you can fix it by running your migrations one at a time using the --fake option on any changes that are in reality already in the database. The fake option just writes the row to the django_migrations table marking the migration as done. Only do this if the database does in fact already have all the changes contained in that migration file.
And those migration files that contain only changes which have not been applied to the database, run without the --fake option and Django will apply them. eg:
# database already has it
manage.py migrate myapp 0003 --fake
# need it
manage.py migrate myapp 0004
# database already has it
manage.py migrate myapp 0005 --fake
If you have migration files where some but not all of the changes have been applied, then you have a bigger problem. In that case, there are several ways to go about it (choose ONLY ONE):
Edit the migration files to put changes that have already been applied (whether Django did it or you did it manually does not matter) into lower number migrations, and put everything you need done into higher numbered files. Now you can --fake the lower number ones, and run the higher numbered ones as normal. Let's say you have 10 changes you made to your models, and 5 of those changes are actually in the database already, but Django doesn't know about them.. so when you run makemigrations, a new migration is created with all 10 changes. This will normally fail because the database server can't for example add a column that already exists. Move these already-applied changes out of your new migration file, into the previous (already applied) migration file. Django will then assume that these were applied with the previous migration and will not try to apply them again. You can then migrate as normal and the new changes will be applied.
If you don't want to touch your older migration file, a cleaner way to do this is to first run makemigrations --empty appname to create an empty migration file. Then run makemigrations which will create another migration with all the changes that Django thinks need to be done. Move the already done migrations from that file into the empty migration you created.. then --fake that one. This will put Django's understanding of what the database looks like will be in sync with reality and you can then migrate as normal, applying the changes in the last migration file.
Get rid of any new migrations you just created using makemigrations. Now, comment out or put back anything in your models that has not been applied to the database, leaving your code matching what's actually in the database. Now you can do makemigrations and migrate appname --fake and you will get things back in sync. Then uncomment your new code and run 'makemigrations' then migrate as normal and the changes will be applied. If the changes are small (for example, adding a few fields), sometimes this is easiest. If the changes are large, it isn't....
You can go ahead and (carefully) make the database changes yourself, bringing the database up to date. Now just run migrate --fake and if you didn't mess up then everything will be ok. Again, this is easy for smaller changes, not as easy for complicated ones.
You can run manage.py sqlmigrate > mychanges.sql. This generates mychanges.sql containing all the SQL Django WOULD have executed against the database. Now edit that file to remove any changes that have already been applied, leaving what needs to be done. Execute that SQL using pgadmin or psql (you're using postgresql I hope). Now the changes have all been made.. so you can run manage.py migrate --fake, this will bring Django into sync with reality and you should be all set. If your SQL skills are sufficient, this is probably the most straightforward solution.
I should add two warnings:
First, if you apply a later migration, eg 0003_foobar.py, and then things don't work out and you decide to try going back and apply 0002_bazbuz.py, then Django will TAKE STUFF OUT OF YOUR DATABASE. For example a column you might have added in 0003 will be dropped along with its data. Since you say you can't lose data, be very careful about going back.
Second, do not rush into running --fake migrations. Make sure that the entire migration you are about to fake is actually in the database already. Else it gets very confusing. If you do regret faking migrations and don't want to roll back, you can erase django's knowledge of the faked migration by deleting that row from the django_migrations table. It is ok to do this.. if you understand what you are doing. If you know that the migration really was not applied, then it's ok.
This blog post really nails it. https://simpleisbetterthancomplex.com/tutorial/2016/07/26/how-to-reset-migrations.html
Let me summarize the steps in his scenario 2 (you have a production database and want to change schema/models in one or more apps). In my case, I had two apps, queue and routingslip, that had model modifications that I needed to apply to a production system. Key was I already had the database, so this is where --fake-initial comes into play.
Here are the steps I followed. As always, backup everything before starting. I do work in a VM so I just took a snapshot before going forward.
1) Remove the migration history for each app.
python manage.py migrate --fake queue zero
python manage.py migrate --fake routingslip zero
2) Blow away any migration files in the entire project within which the app(s) reside.
find . -path "*/migrations/*.py" -not -name "__init__.py" -delete
find . -path "*/migrations/*.pyc" -delete
3) Make migrations
python manage.py makemigrations
4) Apply the migrations, faking initial because the database already exists and we just want the changes:
python manage.py migrate --fake-initial
Worked great for me.
If you don't have any migration files or you lost the previous file and want to migrate new changes, then you need to follow the following steps carefully:
# To create a new migration file before changing the models.
cmd: python manage.py makemigrations app_name
# Fake migrate
cmd: python manage.py migrate app_name 0005 --fake #[0005 is the migration file number created just now. It'll seem like 0005_add_address or something like this.]
# To create a new migration file after changing the models.
cmd: python manage.py makemigrations app_name
# database already has it
cmd: python manage.py migrate app_name 0006 #[0006 is the migration file number created just now.]
I upgrade to django 1.7
and need to deal with migration
My database already exists tables
Here is my step :
1.I delete the migration in django app test
2.I remove south(from INSTALLED APPS ) in django settings.py
3.run python manage.py makemigrations test
Migrations for 'test':
0001_initial.py:
- Create model Person
- Create model Book
- Create model Artical
run python manage.py migrate test
Operations to perform:
Apply all migrations: test
Running migrations:
Applying test.0001_initial... FAKED
is it right???
How to do migration if I already have tables?
Please guide me Thank you
it is right if the tables that exist in your database have the same structure as your current models (i.e. you haven't modified your models.py file after you applied you last migrations with South). If that's the case, you can proceed without worries.
If the structure is different, you can try different approaches:
Create the needed migrations manually. You will have to write your own migration with the needed modifications. Here you can find some example code of a migrations file for altering or adding fields and here you have the complete reference of the methods you can call
Modify your database manually with phpmyadmin, raw sql or the method you prefer.
Do a python manage.py dumpdata app1 app2 app3 > data.json, remove the db, create it again and to a python manage.py loaddata data.json. This may raise some errors because the data you saved was with the old structure, you will have to deal with each error.
Or the least preferred, if the data you had is not needed, just remove the db and recreate it.
There is nothing wrong with the way you are doing it.
The reason the first migration is faked is because your tables are already created:
Run python manage.py migrate. Django will see that the tables for the
initial migrations already exist and mark them as applied without
running them.
From the documentation on upgrading from South.