DEV Community

Cover image for I Got Tired of Manually Managing INSTALLED_APPS in Django, So I Built a CLI Tool
K R Rohan
K R Rohan

Posted on

I Got Tired of Manually Managing INSTALLED_APPS in Django, So I Built a CLI Tool

Every Django developer knows this moment.

You just installed a new package. You open settings.py, scroll down to INSTALLED_APPS, and then you pause — "wait, is it djangorestframework or rest_framework?" You google it. You add it. You go back to the terminal, manually add it to requirements.txt with the right version. Then you do this same thing for the next package. And the next.

It's not painful enough to complain about loudly — but it's annoying enough that I kept thinking there has to be a better way.

So I built one: django-include-apps, a CLI tool that handles all of this for you.


The Problem

If you've worked with Django long enough, you know that pip package names and INSTALLED_APPS names are often completely different things:

What you pip install What you add to INSTALLED_APPS
djangorestframework rest_framework
django-cors-headers corsheaders
django-filter django_filters
django-debug-toolbar debug_toolbar
django-allauth allauth
django-crispy-forms crispy_forms

There's zero standardization here. Every package author picks whatever they want. And if you're new to Django, this is genuinely confusing. If you're experienced, it's just friction that adds up every single day.

On top of that, there's requirements.txt to keep updated. And if you're removing a package — do you remember which pip name maps back to which app? Probably not off the top of your head.


What django-include-apps Does

It automates the whole flow. Install the package, add it to INSTALLED_APPS, update requirements.txt — all from one command.

pip install django-include-apps
Enter fullscreen mode Exit fullscreen mode

Adding a single package

django-include-apps add-app djangorestframework
Enter fullscreen mode Exit fullscreen mode
Installing package 'djangorestframework'...
Package 'djangorestframework' has been installed.
Using 'rest_framework' as the app name for INSTALLED_APPS.
App 'rest_framework' has been added to INSTALLED_APPS.
? Add 'djangorestframework==3.14.0' to requirements.txt? Yes
Added 'djangorestframework==3.14.0' to requirements.txt
Enter fullscreen mode Exit fullscreen mode

That's it. No context switching, no googling, no manual edits.

Adding multiple packages at once

Starting a new project? You can batch install everything:

django-include-apps add-apps djangorestframework django-cors-headers django-filter
Enter fullscreen mode Exit fullscreen mode
Installing package 'djangorestframework'...
App 'rest_framework' has been added to INSTALLED_APPS.

Installing package 'django-cors-headers'...
App 'corsheaders' has been added to INSTALLED_APPS.

Installing package 'django-filter'...
App 'django_filters' has been added to INSTALLED_APPS.

? Add all packages to requirements.txt? Yes
Added 3 packages to requirements.txt
Enter fullscreen mode Exit fullscreen mode

One command, everything wired up.


How the Package Mapping Works

This was the trickiest part to build. The tool ships with 75+ pre-configured mappings for the most common Django packages, so it already knows that djangorestframework maps to rest_framework, and so on.

For packages not in the list, it prompts you interactively:

django-include-apps add-app my-custom-package
Enter fullscreen mode Exit fullscreen mode
Package 'my-custom-package' has been installed.
? Do you want to use the same name or a different one?
  > Use same
    Use different
    None/Skip

Enter app name to add to INSTALLED_APPS: my_custom_app
App 'my_custom_app' has been added to INSTALLED_APPS.
? Save this mapping (my-custom-package → my_custom_app) for future use? Yes
Saved mapping: my-custom-package → my_custom_app
Enter fullscreen mode Exit fullscreen mode

It saves the mapping so next time you don't have to think about it again. You can also manage mappings directly:

# View all 75+ mappings
django-include-apps view-mappings

# Filter by name pattern
django-include-apps view-mappings --filter "django-*"

# Add a custom mapping manually
django-include-apps mapping add my-package my_app_name
Enter fullscreen mode Exit fullscreen mode

Removing Apps

Removing is just as clean:

django-include-apps remove-app rest_framework
Enter fullscreen mode Exit fullscreen mode
? Are you sure you want to remove 'rest_framework' from INSTALLED_APPS? Yes
App 'rest_framework' has been removed from INSTALLED_APPS.
? Remove 'djangorestframework' from requirements.txt? Yes
Removed 'djangorestframework' from requirements.txt
Enter fullscreen mode Exit fullscreen mode

It handles the reverse mapping automatically — so you don't need to remember that rest_framework came from djangorestframework.

For multiple apps:

django-include-apps remove-apps rest_framework corsheaders django_filters
Enter fullscreen mode Exit fullscreen mode

Core Django apps (django.contrib.*) are protected from removal, so you can't accidentally nuke something critical.


My Favourite Feature: Unused App Detection

This one I didn't even plan originally — it just made sense once I started thinking about the removal flow.

Run remove-app with no arguments and it scans every .py file in your project, looking for apps in INSTALLED_APPS that aren't actually imported anywhere:

django-include-apps remove-app
Enter fullscreen mode Exit fullscreen mode
Scanning project for unused apps...

Found 3 unused app(s):
  • rest_framework
  • corsheaders
  • debug_toolbar

? Select apps to remove (use space to select, enter to confirm)
  ◉ rest_framework
  ◯ corsheaders
  ◉ debug_toolbar

App 'rest_framework' has been removed from INSTALLED_APPS.
App 'debug_toolbar' has been removed from INSTALLED_APPS.

? Remove selected packages from requirements.txt? Yes
Removed 2 packages from requirements.txt
Enter fullscreen mode Exit fullscreen mode

You get a checkbox UI so you can pick exactly what to clean up. It won't touch Django defaults.

This is genuinely useful for projects that have grown over time and accumulated packages that nobody uses anymore.


Version Specifiers Work Too

If you need a specific version, just pass it in:

# Exact version
django-include-apps add-app djangorestframework==3.14.0

# Minimum version
django-include-apps add-app django-filter>=2.0

# Compatible version
django-include-apps add-app django-cors-headers~=4.0.0

# Multiple with versions
django-include-apps add-apps djangorestframework==3.14.0 django-filter>=2.0
Enter fullscreen mode Exit fullscreen mode

It strips the version specifier for mapping lookups, then uses the full spec for pip and requirements.txt.


requirements.txt Handling

The tool is smart about what state your requirements.txt is in.

If it exists — it appends or updates the package.

If it doesn't exist yet — it gives you options:

? requirements.txt not found. What would you like to do?
  > Create requirements.txt with this package
    Create requirements.txt with all project packages
    Skip
Enter fullscreen mode Exit fullscreen mode

The second option is handy — it scans your INSTALLED_APPS and generates a full requirements.txt from everything currently installed.


Installing from requirements.txt

If you clone a project and want to install dependencies and auto-configure INSTALLED_APPS:

django-include-apps install-requirements -r requirements.txt
Enter fullscreen mode Exit fullscreen mode
Found 15 package(s) in requirements.txt
Installing packages...
Successfully installed packages from requirements.txt

Detecting Django-related packages...
Found 5 Django package(s):
  • djangorestframework → rest_framework
  • django-cors-headers → corsheaders
  • django-filter → django_filters
  • django-allauth → allauth
  • celery (not mapped)

? Select packages to add to INSTALLED_APPS:
  ◉ djangorestframework (rest_framework)
  ◉ django-cors-headers (corsheaders)
  ◯ django-filter (django_filters)
  ◉ django-allauth (allauth)

✓ Added 'rest_framework' to INSTALLED_APPS
✓ Added 'corsheaders' to INSTALLED_APPS
✓ Added 'allauth' to INSTALLED_APPS
Enter fullscreen mode Exit fullscreen mode

Shell Completion

Auto-complete for bash, zsh, and fish is built in:

# Install for bash
django-include-apps completion bash --install

# Install for zsh
django-include-apps completion zsh --install

# Install for fish
django-include-apps completion fish --install
Enter fullscreen mode Exit fullscreen mode

Then restart your terminal and tab completion just works.


Working with Multiple Projects

Every command supports --start-dir (or -d) if you're running from outside the project root or working with a monorepo:

django-include-apps add-app djangorestframework -d /path/to/my/django/project
django-include-apps install-requirements -r requirements.txt -d /path/to/project
Enter fullscreen mode Exit fullscreen mode

Some Packages That Are Already Mapped

Here's a small sample of the 75+ packages that are pre-configured:

Package App Name
djangorestframework rest_framework
django-cors-headers corsheaders
django-allauth allauth
channels channels
django-storages storages
django-redis django_redis
django-taggit taggit
django-guardian guardian
django-oauth-toolkit oauth2_provider
django-import-export import_export
django-jazzmin jazzmin
celery celery
daphne daphne

Packages like pillow, psycopg2, gunicorn, and mysqlclient are also mapped — but correctly marked as dependency-only, so they won't be added to INSTALLED_APPS.

See the full list of mappings on GitHub →


What's Coming Next

There's a lot I want to add. Things on the roadmap:

  • Middleware management
  • URL config suggestions
  • Settings detection
  • .env file generation
  • Package update checker
  • Project scaffolding

If any of these sound useful — or you have ideas I haven't thought of — open an issue and I'll add it to the roadmap.


Try It Out

pip install django-include-apps
Enter fullscreen mode Exit fullscreen mode

If you run into any issues or a package mapping is missing, PRs are very welcome. Adding a new mapping is literally just one line in a JSON file — it's a great first contribution if you're looking for one.


If this saved you some time, a ⭐ on GitHub would mean a lot — it helps others find the project too!

Built this out of frustration during a project setup. It's crossed 7,800+ downloads since release — turns out a lot of people have the same frustration. Hope it saves you some time too.

Top comments (0)