migrate and yet Django dares to throw an error? Incomparable betrayal! Let’s look through several cases.
For ages encountering migrations errors, I have been wipin the entire database and migrations files. Until one day an error occurred at a production server. There was no other option but to calm down and learn how to fix it.
🧸 Relation does not exist 1: not applied by you or Django
Run the command
showmigrations and look at the output. If you see something like this:
firstapp [X] 0001_initial [X] 0002_auto_20190819_2019 [X] 0003_auto_20190827_2311 [ ] 0004_testunit
That means that the 0004 migrations was not applied, so just run
migrate. If it stays misapplied or to avoid wasting time you can run this:
migrate firstapp 0004_testunit
If not, look further.
💔 Relation does not exist 2: You removed a migration’s file
The point of each migrations is to find the difference between the last version of the database structure and the current one. But Django does not look at the database itself, it compares your current
models.py files with a virtual database made from
migrations.py files. Then Django writes the changes down in new migrations files. And only with
migrate you apply these changed to the database.
So if you remove something from
migrations/ folder, the database will stay the same, but the Django’s idea of it won’t.
So, you added a field type to a class Tag:
class Tag(models.Model) name = models.CharField(max_length=100) type = models.CharField(max_length=100)
You made a migrations, say, number
0002, it contains adding
type field. Then you removed the migrations. After that, you made some changes, lived your best live, and decided to make migrations again.
Django will include creation of the
type field to the migrations again. Therefore applying this migrations will give you an error:
ProgrammingError: column "tag_type" of relation "tag" already exists
How to Solve it 🧰
1. From migration file
0002_something.py remove the line about creating the type field.
from django.db import migrations, models class Migration(migrations.Migration): dependencies = [ ('firstapp', '0002_something'), ] operations = [ ... # This .AddField below: migrations.AddField( model_name='tag', name='type', field=models.Charfield(max_length), ), ... ]
2. Migrate the
migrate firstapp 0002_something
3. Make a new migration (it must only contain creating the type field):
4. Fake apply it like this:
migrate firstapp 0003_something_two --fake
🔨 Relation does not exist 2: Renaming a field was not applied
This mysterious thing happened. I renamed
type_name and I have a migrations that states it:
... operations = [ migrations.RenameField( model_name='tag', old_name='type', new_name='type_name', ), ] ...
And yet I get this error:
ProgrammingError at /test relation "firstapp_tag_type_name" does not exist
Possible culprit (myself and mass replace) a.k.a Sloppy Development installment
While changing names in the whole project automatically, I also unwillingly changed them in the migrations files. It is a great temptation to remove it all at once, but be careful. That may be the problem.
How to Solve it 🧰
Attempt #1: Order is wrong
type field may have been altered before it was created because of the mass replace.
Try finding the whole life cycle of
type field in your migrations – where it was added, where it was altered etc.
Attempt #2: Remove Migration file concerning the field
Remove every mention of the type field in migrations’ files (in
operation). Then do whatever you want (rename it etc.) and make a migration again.
If the change is the only one in a migrations file, remove it all together.
You can remove the whole migration file, if it only contains
type field manipulations. But be careful and alter
dependencies for the following migration file (replace the deleted file’s name with the one before it).
Say, migrations’s files are
0003_something.py (removed) and
So, after deleting
dependencies = [ ('firstapp', '0003_something'), ]
dependencies = [ ('firstapp', '0002_something_before'), ]
Otherwise you will get an error like this:
django.db.migrations.exceptions.NodeNotFoundError: Migration firstapp.0003_something_something dependencies reference nonexistent parent node
Attempt #3: Remove every mention of the problematic field
If simply removing a migration and making another one doesn’t help…
Embrace yourself and remove every mention of
type field. For my personal project, that inspired this post, it was quite time consuming.
However, as I see it now, you can’t just remove the field and make migrations of that, because type does not exist in the database. However, I can’t answer why.
You need to remove it from everywhere.
makemigrations must show nothing, and the error won’t make am appearance.
🚫 Why you shouldn’t remove migrations
Summing up, Django does not care about database itself, except for when it returns errors. So Django’s idea of the database is made of migrations it have. That’s why when you run
makemigrations, you get errors about migration files.
After applying new migrations, you will start getting all sorts of surprises:
InvalidCursorName cursor does not exist or good old
ProgrammingError: column does not exist and
ProgrammingError: column of relation already exists.
Take my advice – don’t remove migrations because of migration errors, better learn how to work with them. Because in production you won’t be able to flush the database without a trouble (you kind of can, but you will need to insert missing data afterwards).
But if you did remove migrations…
Oh, been there.
I can say one thing – you will need to keep reversing changes to the database until you don’t get any more errors. And then make this changes again the same way I showed you here. And while in most cases Attempt #3 works, some day it may fail you.
One day I will emulate this and come back and update this post with a quick solution, but now I am triggered enough by just the mention of it.
Transforming one field to another
You can transform pretty much everything with an exception.
Adding a through table to M2M relation (or backwards)
Usually you want to add a through table to store additional data about the relation, not remove it. Either way, Django won’t allow this transition.
Say, Django can remove all the additional data, but constraints like
unique_together can ruin your architecture. So you need to do it manually.