Not always you have project structure perfect right from the start. Probably never actually. And during development you might realise that your application named "app" isn't very descriptive. And then you might have "default_app". So you decide to go and rename it. But it's not so easy with Django.
If you want to rename Django app you need to go through a couple of stages. Final stage might not be neccessary if you're lucky enough.
1. Rename app directory.
2. Change name in your code.
3. Run DB migrations.
4. Migrate tables manually.
Directory level
This one is very easy. You just go and rename a directory. Nothing will stop from this.
Code search & replace
After you renamed your directory, next step would be to go and update your references in code. If you're using IDE it probably has an LSP based "search & replace". If you're like me using neovim, then I'd suggest to use combination of Telescope Grep and quickfix list.
Make sure that all your references in settings.py
are properly updated. Also make sure to rename your Config class name. Overall it should be pretty straightforward.
Migrations
After you've updated all your code references, time to migrate database entries. You've already made some migration before, please make sure that in the "migrations" directories you've updated references to your app as well.
Then call
python manage.py makemigrations
python manage.py migrate
Or if you're running your app in docker
docker exec python manage.py makemigrations
docker exec python manage.py migrate
And now if you're lucky - you should be all done! Easy and painless!
But you're unlucky
After all that's done, you might get different errors. There's a different variety, but one of the most common would be about initial migration. You can solve that issue in 2 ways:
1. Flush database. Start from scratch.
2. Manually update entries.
I'll assume that you don't want to clear your database, so let's go and modify entries manually. I will give intrsuctions with the idea that your app runs in docker image, since this is where it might be a little bit trickier to get to DB. And I'm mainly using Postgres.
Access the PostgreSQL container
Open your terminal and run the following command to access the PostgreSQL container. Replace yourservicename with the name of your PostgreSQL service defined in your docker-compose.yml file.
docker-compose exec your_service_name bash
Connect to the PostgreSQL database
Once inside the container, connect to the PostgreSQL database using the psql command. Replace yourdatabasename and yourusername with your actual database name and username.
psql -U your_username -d your_database_name
Run the SQL query
After connecting to the database, you can run your SQL query.
UPDATE django_content_type SET app_label='new_name' WHERE app_label='old_name';
This one should do the trick. But if doesn't, it means that you might need to update all the tables by hand. It will depend on an error.
Inconsistent history error
If you get errordjango.db.migrations.exceptions.InconsistentMigrationHistory then it means that your app is being referenced during migration_001 and there're might some sort of recursive dependency. Doing fake migration might do the trick.
You can fake the initial migration for the articles app to ensure that Django considers it as already applied. Run the following command:
python manage.py migrate new_app_name 0001_initial --fake
If fake migration didn't work.
If fake migration didn't work, then let's try to delete the migration files in the migrations directories of the affected apps. Make sure to keep the init.py file.
Connect to your PostgreSQL database and delete the migration records for the affected apps:
DELETE FROM django_migrations WHERE app='affect_app_name';
After that, make migrations and apply them again. This should start you from scratch.
Updating all the tables
In case you're still struggling - you probably need to update all the tables. Here're queries that you need.
Update django_migrations table
UPDATE django_migrations SET app = 'new_name' WHERE app = 'old_name';
Update django_content_type table
UPDATE django_content_type SET app_label = 'new_name' WHERE app_label = 'old_name';
Update auth_permission table
UPDATE auth_permission SET content_type_id = (SELECT id FROM django_content_type WHERE app_label = 'new_name' AND model = 'your_model_name')
WHERE content_type_id = (SELECT id FROM django_content_type WHERE app_label = 'old_name' AND model = 'your_model_name');
Update any custom tables
UPDATE your_custom_table SET app_label = 'new_name' WHERE app_label = old_name';
Update django_admin_log table
UPDATE django_admin_log SET content_type_id = (SELECT id FROM django_content_type WHERE app_label = 'new_name' AND model = 'your_model_name')
WHERE content_type_id = (SELECT id FROM django_content_type WHERE app_label = 'old_name' AND model = 'your_model_name');
And you want to update your table names.
ALTER TABLE old_table_name RENAME TO new_table_name;
Usefull commands
Access bash of container
docker-compose exec your_service_name bash
Connect to database
psql -U your_username -d your_database_name
List all users
\du
List all databases
After connecting to PostgreSQL, run the following command to list all databases:
\l
Final words
These snippets should get you through most edge cases. It's a bit pain in the ass, but that's we pay for the convenience of Django.