IntegrityError on loaddata restore into non-empty database with existing primary keys
0 reputation · 14 Feb 2020, 08:26 UTC
0 reputation · 14 Feb 2020, 08:26 UTC
When using dumpdata to export a Django project's data and loaddata to restore it, the default behavior inserts fixture rows without removing existing rows in the target database. This design leads to primary-key collisions or unique-constraint violations if the destination already contains rows with the same identifiers. The fixture format also omits database-specific sequence state, so auto-increment counters are not reset, causing subsequent INSERT statements to generate conflicting IDs even after a seemingly successful load.
The goal is to understand the exact failure modes when loaddata encounters pre-existing data across supported backends (PostgreSQL, MySQL, SQLite) in Django 4.2–5.x, and whether any built-in option or transaction wrapper can make the operation idempotent without a full flush.
loaddata --ignore or any other flag suppress IntegrityError for duplicate primary keys while still loading non-conflicting rows?35775 reputation · 14 Feb 2020, 13:43 UTC
When loaddata is invoked, Django wraps all fixture rows in a single database transaction. If any row violates a primary‑key or unique constraint, the whole transaction rolls back and an IntegrityError is raised. No flag exists to skip conflicting rows; the --ignore option only prevents loading of the whole fixture file.
--ignore flag does not suppress IntegrityError for duplicate primary keys. It merely prevents loading of the entire fixture file, so any partially loaded file that contains duplicate keys will still cause a rollback.INSERT. The sequence is not reset, so subsequent inserts may attempt to reuse already‑taken identifiers unless the sequence is manually advanced.SELECT MAX(id) FROM app_model_id_seq;) and check for duplicate keys (SELECT id, COUNT(*) FROM app_model GROUP BY id HAVING COUNT(*)>1).Steps to make the restore idempotent without a full flush:
python manage.py loaddata . The command will succeed because the tables are empty.SELECT MAX(id) FROM app_model_id_seq; and compare to SELECT MAX(id) FROM app_model;. If they differ, reset the sequence with SELECT setval('app_model_id_seq', (SELECT MAX(id) FROM app_model), true);.If you are using a specific backend, let me know which database (PostgreSQL, MySQL, or SQLite) you are targeting so I can provide the exact sequence‑reset command for that system.
Use comments to ask for clarification. Post a solution as an answer.
35,775 reputation · 14 Feb 2020, 09:28 UTC
After a loaddata run, compare the sequence’s last_value with the highest primary key in the target table. Use SELECT last_value FROM ; and SELECT MAX(id) FROM ;. If they differ, reset with SELECT setval('sequence_name', (SELECT MAX(id) FROM model), true);. Then run a duplicate‑key check: SELECT id, COUNT(*) FROM GROUP BY id HAVING COUNT(*)>1;. This ensures no orphaned sequence state and no hidden PK conflicts.