I am migrating a project from Django 1.1 to Django 3.0 I am done with the project. When I am dumping the production dump to my local in the newly converted project I get "Table already exists".
Here's what I am doing.
mysql> create database xyx;
docker exec -i <container-hash> mysql -u<user> -p<password> xyx < dbdump.sql
then I run the migrate, as I have had to do some changes to the previously given models.
./manage.py migrate --fake-initial
this is the output I get
_mysql.connection.query(self, query)
django.db.utils.OperationalError: (1050, "Table 'city' already exists")
So, what to do ?
Alright boys and girls, here's the approach I followed to solve this problem.
I dumped the entire database.
docker exec -i <container-hash> mysql -u<username> -p<password> <dbname> < dump.sql
Now I listed all the migrations I made using
./manage.py showmigrations <app-name>
This will give me the list of all the migrations I have applied, now from inspecting the migrations, I realized that from the 7th migration to the 30th migration I had done my changes.
Here's the tedious part which any sys admin can write a script to do in less than 4 lines of bash script. You can generate the raw SQL of any migration with this command.
./manage.py sqlmigrate <app-name> <migration-name> > changes-i-made.sql
Now that I have created my changes-i-made.sql file I'll need to run this script 22 more times but with >> otherwise everytime you run the command with a single > it will keep overwriting your changes file.
Now once all of your migration changes are recorded inside a file, open up your sql shell connect to the database and start pasting the changes or do some sql magic to pick all the changes directly from the file.
Once you're done go ahead and fake all the migrations, cause you don't need Django to do them you already did.
./manage.py migrate --fake
and then login to your production instance and get ready to fuck with your senior team lead who said you couldn't do it.
I just checked to see if this approach is working and the future migrations will be working, so I created one and everything works like a breeze.
Foreground
Hi. I´m uploading my Django app database to my Heroku production environment. When I try to manage.py loaddata I get the following error:
django.db.utils.IntegrityError: Problem installing fixtures: insert or update in table "catalog_contactos" violates key constraint.
I found this post where someone suggests that first you should load models that are the base for foreign key: related post
Also I found this post that refers to moving a database to another app (the production version for example). Basically it says:
When you backup whole database by using dumpdata command, it will
backup all the database tables
If you use this database dump to load the fresh database(in another
django project), it can be causes IntegrityError (If you loaddata in
same database it works fine)
To fix this problem, make sure to backup the database by excluding
contenttypes and auth.permissions tables
Link to the post
My code
Following that suggestions I do:
python manage.py dumpdata --exclude auth.permission --exclude contenttypes > data.json
Then on the server I run the following code and get the integrity error:
heroku run python manage.py loaddata data.json
Should I dumpdata model by model and loaddata them in a certaing order? Or I´m coding something wrong? Any clues?
Thanks in advance!
Update
Could this "Natural keys" issue be the solutuion? Django serializing objects
When I had integrity error with django/postgreSQL I did DROP TABLE table in postgreSQL.
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.
I have a PostgreSQL database that where I performed python manage.py dumpdata to backup the data into a json file. I created a new PostgreSQL database, performed a migrate, and everything worked like clockwork. When I tried to load the backup.json file with python manage.py loaddata backup.json it, gives me this error.
Could not load contenttypes.ContentType(pk=15): duplicate key value violates unique constraint "django_content_type_app_label_76bd3d3b_uniq"
DETAIL: Key (app_label, model)=(navigation, navigation) already exists.
I checked phpPgAdmin, and there is a row for News. Is there a way to load the backup json file without including the content types, or better yet dump everything except for content types data ?
I was getting similar error:
django.db.utils.IntegrityError: Problem installing fixture
'/home/knysys/ogmius/ogmius/db.json': Could not load
contenttypes.ContentType(pk=2): duplicate key value violates unique
constraint "django_content_type_app_label_model_76bd3d3b_uniq" DETAIL:
Key (app_label, model)=(auth, user) already exists
After that, I found out that If you are restoring a fresh database from another database, You need to dumpdata like this:
./manage.py dumpdata --exclude auth.permission --exclude contenttypes > db.json
and then load fresh database like this:
./manage.py loaddata db.json
You can use the following command to load data:
python manage.py loaddata --exclude auth.permission --exclude contenttypes back.json
I run python manage.py makemigrations and I get:
No changes detected
Then, python manage.py migrate and I get:
No migrations to apply.
Then, I try to push the changes to production:
git push heroku master
Everything up-to-date
Then, in production, I repeat the command:
heroku run python manage.py migrate
No migrations to apply.
Just in case, I run makemigrations in production:
heroku run python manage.py makemigrations
No changes detected
WHY then I get a
ProgrammingError at ....
column .... does not exist
"No changes detected" means the database is coherent with the code.
How can I debug this?¡?
I got the same problem (column not exist) but when I try to run migrate not with makemigrations (it is the same issue I believe)
Cause: I removed the migration files and replaced them with single pretending intial migration file 0001 before running the migration for the last change
Solution:
Drop tables involved in that migration of that app (consider a backup workaround if any)
Delete the rows responsible of the migration of that app from the table django_migrations in which migrations are recorded, This is how Django knows which migrations have been applied and which still need to be applied.
And here is how solve this problem:
log in as postgres user (my user is called posgres):
sudo -i -u postgres
Open an sql terminal and connect to your database:
psql -d database_name
List your table and spot the tables related to that app:
\dt
Drop them (consider drop order with relations):
DROP TABLE tablename ;
List migration record, you will see migrations applied classified like so:
id | app | name | applied
--+------+--------+---------+
SELECT * FROM django_migrations;
Delete rows of migrations of that app (you can delete by id or by app, with app don't forget 'quotes'):
DELETE FROM django_migrations WHERE app='yourapp';
log out and run your migrations merely (maybe run makemigrations in your case):
python manage.py migrate --settings=your.settings.module_if_any
Note: it is possible that in your case will not have to drop all the tables of that app and not all the migrations, just the ones of the models causing the problem.
I wish this can help.
Django migrations are recorded in your database under the 'django_migrations' table. This is how Django knows which migrations have been applied and which still need to be applied.
Have a look at django_migrations table in your DB. It may be that something went wrong when your migration was applied. So, delete the row in the table which has the migration file name that is related to that column that 'does not exist'. Then, try to re-run a migration.
Here's what i tried and it worked:
Go and add manually the column to your table
run python manage.py makemigrations
go back drop that column you added
run python manage.py migrate
I had a similar issue - the error message appeared when I clicked on the model on the django-admin site. I solved it by commenting out the field in models.py, then running migrations. Following this I uncommented the field and re ran the migrations. After that the error message disappeared.
My case might be a bit obscure, but if it helps someone, it is worth documenting here.
I was calling a function in one of my migrations, which imported a Model of said migration regularly, i.e.
from myApp.models import ModelX
The only way models should be imported in migrations would be using e.g. RunPython:
def myFunc(apps, schema_editor):
MyModel = apps.get_model('myApp 'MyModel')
and then calling that function like so:
class Migration(migrations.Migration):
operations = [
migrations.RunPython(initialize_mhs, reverse_code=migrations.RunPython.noop),
]
Additionally the original import worked until I modified the model in a later migration, making this error harder to locate.
So, I always run into this sort of problem, so today I decided to try and work it out at the database level. Thing is, I changed a model field name which Django didn't bother reflecting in a migration file. I only found out later when I ran into problems. I later looked at the migration files and discovered there was no migration for that change. But I didn't notice because I made other changes as well, so once I saw a migration file I was happy.
My advice. Create migration for each change one at a time. That way you get to see if it happened or not.
So here's my working through it in MySQL.
open mysql console.
show databases; # see all my dbs. I deleted a few
drop database <db-name>; # if needed
use <db-name>; # the database name for your django project
show tables; # see all tables in the database
DESCRIBE <table-name>; # shows columns in the database
SHOW COLUMNS FROM <db-name>; # same thing as above
ALTER TABLE <table-name> CHANGE <old-column-name> <new-column-name> <col-type>; # now I manually updated my column name
If you're using postgresql, just google the corresponding commands.
The issue was in the Models for me, for some reason Django was adding '_id' to the end of my Foreign Key column. I had to explicitly set the related named to the Foreign Key. Here 'Cards' is the parent table and 'Prices' is the child table.
class Cards(models.Model):
unique_id = models.CharField(primary_key=True, max_length=45)
name = models.CharField(max_length=225)
class Prices(models.Model):
unique_id = models.ForeignKey(Cards, models.DO_NOTHING)
Works after changing to:
class Cards(models.Model):
unique_id = models.CharField(primary_key=True, max_length=45)
name = models.CharField(max_length=225)
class Prices(models.Model):
unique_id = models.ForeignKey(Cards, models.DO_NOTHING, db_column='unique_id')
When I get this error, my extreme way to solve it is to reset my database:
Reset your database
For Postgresql on Heroku:
Heroku > your_app > Resources > database > add-ons > click on your database and open it
For postgresql
settings > Reset database
Delete all files in your_app > migrations > __pycache__ except __init.py__
Delete all files in your_app > migrations except __pycache__ folder and __init.py__
Then run:
python manage.py makemigrations
python manage.py migrate
python manage.py createsuperuser
type in to create your superuser, then run:
python manage.py makemigrations
python manage.py migrate
python manage.py
If you are able to inspect your models from your admin section, then it should be all okay now.
Just remove corresponding row migrations for that model in 'django_migrations' model in database.
And re run python manage.py migrate app_name
I tried all these answers with not much luck! What I did to have this problem solved with no harm was to go back through the migration files and find where the actual model was being created for the first time then manually add the field (in the column not being existed error message). Until if you run makemigrations --dry-run you get/see "No changes detected" and that worked. Basically, in my case, I had to carefully take my desired db changes back in time in proper migration file, rather creating a new migration now at the end of migration dependency chain.
Open the latest py file created after running the makemigrations command inside migrations folder of that particular app.
Inside class Migration there is a list attribute called 'operations'.
Remove the particular elements migrations.RemoveField(...).
Save and run python manage.py migrate.
A easier solution to the problem is to make your models exactly like it is in the migration first. and run python manage.py migrate.
Then revert those changes
Run
python manage.py makemigrations
python manage.py migrate
To check for which migrations are applied and which are not, use -:
python manage.py showmigrations
I solved a similar problem by deleting all migrations files (Don't forget to make a backup) and python manage.py makemigrations all of them into one clean file in development and pulling new files on the server. Before then I had dropped existing tables on the PostgreSQL.
I was getting this error for some reason when Django was looking for a column of type ForeignKey named category_id when the actual name in the database was category. I tried every Django solution I could imagine (renaming field, explicitly setting column name, etc.). I didn't want to drop tables or rows as this was a production database. The solution was simply to rename the column manually using SQL. In my case:
ALTER TABLE table_name
RENAME COLUMN category TO category_id;
Make sure you backup your database, ensure this won't break any other applications consuming that particular table, and consider having a fallback column if necessary.
What helped me in the end was simply dropping the database and creating it again as well as deleting all migrations files (including cache). (only removing migrations file didn't work for me at all)
sudo su - postgres
psql
DROP DATABASE 'yourdatabase';
CREATE DATABASE 'yourdatabase';
GRANT ALL PRIVILEGES ON DATABASE 'yourdatabase' to 'yourdjangouser';
then just
python manage.py makemigrations
python manage.py migrate
python manage.py runserver
If you're in development and you make some examples of data that's not important, this step is beneficial for me: just flush your data, make migrations, and migrate:
python manage.py flush
python manage.py makemigrations
python manage.py migrate
After that, you may create a new database from scratch, I hope this information was helpful.
Solved this issue by running
python manage.py migrate
in Heroku Bash shell