Django migrations, resolving merging problems - django

As I was changing my models.py and migrating, I got an error message saying:
python manage.py makemigrations project_profile
CommandError: Conflicting migrations detected; multiple leaf nodes in the migration graph: (0033_auto_20180217_0912, 0036_auto_20180217_0927 in project_profile).
To fix them run 'python manage.py makemigrations --merge'
So, when I tried to follow the instructions, I got another error that one of my tables that the merged migration is now depending on do not exist anymore (I renamed it). Interestingly enough, this renaming took place during the merge operation. So, really Django should have known about it in the first place.
To resolve the situation, I deleted prior migrations up to and including the migrations that was not applied, the one that caused all the headache. I tried to makemigrations and migrate again. But, Django now throws another error saying some of the models it wants to create in the database already exist. Obviously, I do not want to delete those tables and loose all that information to appease Django. So, I had to resort to some hacking solutions and actually change those tables manually and do a fake migration in order to stop Django from complaining.
Having said all of that, I feel like there should be a more logical way about this. How do I resolve migrations during the merging?

I had the same issue, Then I was able to solve this by deleting the migrations file that django pointed out and starts with name auto. It occurred 2-3 times before it finally gave up and finally worked.
Alternatively you can django-dbbackup or django-import-export packages to backup the tables then clean your database and migrations. Then you can restore them back to the same state once migrations are stable.
Sources
dbbackup : https://django-dbbackup.readthedocs.io/en/stable/
import-export : https://django-import-export.readthedocs.io/en/latest/index.html

Related

How to ensure consistency between Django models and underlying databases

On our staging server we observed a runtime error stating a field is missing from a database,
column our_table.our_field does not exist
LINE 1: ...d"."type", "our_table"...
The field was added during a recent update with a complicated migration squashing process. It's possible that some errors were made during this process, but "manage.py showmigrations" command shows that the migration has been applied and "manage.py makemigrations" does not create any new migration. As we do not run tests on our staging or production databases, we are trying to figure out the most effective method for identifying such errors.
In short, how can we identify mismatches between the database and Django models caused by an incorrect migration like the following?
python manage.py migrate our_app --fake
I suppose I am looking for something like
python manage.py check_database
Edit: Many thanks for the suggestions. However, this is more of a deployment than a development question because the problem likely occurred when our devops tried to apply the squashed migrations while retaining data on the staging server (which will be case on production). It was scary to learn that such inconsistency can occur when makemigrations and showmigrations do not show any problem and can therefore also happen on production.
The bottom line is that we need some way to ensure our database matches our models after deployment.

Django Migrations stuck after executing in incorrect order

I made two changes to different models in my database.
The first
operations = [
migrations.DeleteModel(
name='Settlement',
),
]
And the second:
operations = [
migrations.RemoveField(
model_name='invoice',
name='settlement_deducted',
),
migrations.RemoveField(
model_name='invoice',
name='settlement_supporting',
),
]
The issue is that they ran in this order, and the second one failed. The field being removed in the second migration uses the "Settlement" model, but since that model was deleted in the first migration it throws this error:
ValueError: The field invoices.Invoice.settlement_deducted was declared with a lazy reference to 'accounting.settlement', but app 'accounting' doesn't provide model 'settlement'.
The field invoices.Invoice.settlement_supporting was declared with a lazy reference to 'accounting.settlement', but app 'accounting' doesn't provide model 'settlement'
Now when I try to do anything to fix it, it seems to just be stuck in that error state and continuously throws that same error.
I have tried reverting the first migration to the previous migration on that model, adding that model back in and running makemigrations and then migrate so that the Settlement model exists again, and deleting the second migration (though it was never run anyway). All of these options are still throwing the same error.
I am surprised that Django didn't catch this dependency issue for me, but it is unfortunately too late for that now. I also tried adding it as a dependency, but then it just threw the error saying that a migration has been migrated before one of its dependencies.
I was successfully able to solve the issue! These are the steps I took:
add the second migration as a dependency to the first one
go to the django_migrations table in the db and delete the first migration (which ran already)
run ONLY the second migration
fake the first migration (since it already ran)
(unnecessary step but necessary in my case) run migrate normally to finish migrating uninvolved migrations from other apps
insite try this
py manage.py migrate <yourappname> zero
then go in the same app folder and in that migration folder delete all the file except pycache and init.py and then again try to run
py manage.py makemigrations
py manage.py migrate
and please do replace py with python if you are using any other Os then windows what the migrate zero do is it delete all the migration of your app and after again doing the migration it will get everything back for you
and tell me if you still got any other error

Django: Safely Remove Old Migrations?

I've got a Django app with a lot of out-of-date migrations. I'd like to remove the old migrations and start fresh.
The app has 14 different "migrations" folders.
Here is what a few of them look like:
Is it safe to remove all the contents from each of these folders? Or, do I have to make sure to only remove some of the files -- and if so which files?
You should never just delete migrations before unapplying them, or it will be a nightmare when you want to apply new migrations.
To unapply migrations you should do the following:
Use the python manage.py migrate your_app_name XXXX in case you want to unapply migrations after the XXXX migration. Otherwise use python manage.py migrate your_app_name zero to completely unapply all migrations.
Remove the .pyc files under /migrations/_pycache_/ that you have unapplied.
Remove the .py files under migrations/ that you have unapplied.
Now you can create new migrations without any headaches.
If what you're looking for is to squash all the migrations into one, do the steps above removing all migrations and then run python manage.py makemigrations your_app_name to create a single migration file. After that just run python manage.py migrate your_app_name and you're done.
That depends. If you have a production database (or any database you cannot simply drop and recreate), then the answer is no, you cannot safely remove migrations.
If you do not have any permanent databases, then yes, you can remove all migrations, run python manage.py makemigrations --initial and it will create fresh migrations based on your current models.
Also, you should check if any of the migrations are custom data migrations written by hand. If there are any, you might want to keep those.
The .pyc files are generally safe to remove, provided the related .py files are still there.
your first screenshot is not Django and looks like a JS project of some sort.
The json and js files are unrelated to the django migrations as well as __pycache__ folder. You can delete all off them.
If you mean "previously applied and no longer needed as the project only needs the latest version of the migrations" you don't want to remove but squash them instead with squashmigrations which reduces the files you have to two, init file and the initial migration file, this way your project still works.
If by remove you mean you no longer need them because you already changed the models so much that the previous migrations aren't even used other than being applied and unapplied without ever being used, doesn't matter, go to step 2 and do that instead of deleting the files manually. When you create migrations on your applications one by one, you also create migration dependency tree, well, django does. And it is really hard to keep track of after some point, if you try to delete everything thinking you can create new migration files with ease, trust me as someone who experienced otherwise, it does not work like that. It is way simpler to let django handle the migration squashing, it optimizes the migration meaning that it also deletes the unused ones in your final state.
More to read at: https://docs.djangoproject.com/en/2.2/topics/migrations/#migration-squashing
Having marked one of the answers provided previously as being accepted, here is a summary of a few things I learned:
Deleting Django migrations is generally a bad idea.
Django keeps track of what's in your db through these migration files, as well as through a table it creates in your db, and if you delete any of this Django will start throwing errors on migrate that can be hard to fix.
I was getting some of those hard-to-fix errors. Here is what I did to fix it:
Ran migrate on the production server.
When I got an error, it would tell me how the db was out of sync with what Django expected. I corrected that manually by directly editing the db with an sql client.
E.g. If it said a key existed that wasn't supposed to exist, I deleted the relevant index from the indicated table.
Or if it said a table existed that wasn't supposed to exist, I backed up the table to a file, and deleted the table. Migrate then created the table, and then I repopulated it with data from the backup.
In the case of many-to-many tables, once Django had re-created them, I deleted all the new Django-created tables, and restored them from a backup created on my local dev system, which had already had all the latest migrations run on it.
Eventually I was able to complete all migrations successfully.
I have a feeling I lucked out and the above won't work in all cases! I've learned a lot about Django and migrations and will be much more careful about this in the future.
when you import from third app:
there are 2 step uninstall it
there are use the 'django_celery_beat' app for example.
step1: clean table
python .\manage.py migrate django_celery_beat zero
step2: remove app from INSTALLED_APPS
there are done!!!
this is django document on this.
How to Reset Migrations
if you are using linux/unix os then you can fire this command. delete all migration directory.
find . -path "/migrations/.py" -not -name "init.py" -delete
find . -path "/migrations/.pyc" -delete

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

"Wrong number of constraints" when refactoring models to another app

After refactoring some models in a bloated app (everything in appname/models.py) into a subfolder application (some of the models in appname/subapp/models.py) and running makemigrations, I'm getting the following error when running manage.py migrate:
ValueError: Found wrong number (2) of constraints for appname_modelname1(modelname2_id)
Getting rid of all migrations and starting over would be one option, but then I'd have to manually edit all existing production databases. Are there any alternatives to make the migrations apply smoothly?
Turns out that ./manage.py makemigrations makes overly complex migrations that will likely fail on a real constraint-enforcing database. If the objective is just to get rid of models, first make the migrations, then edit the migration file so that only the RemoveModel directives remain, and finally apply the migrations.