Fix: Django ImproperlyConfigured Error During Makemigrations or Migrate

Django's development roadmap moves fast. Bleeding edge tech is great but sometimes it's tricky to keep up with quirks that might break backward compatibility. One such case: apps in subdirectories—here's the fix.
django app install error

Django is an incredible web framework that is actively developed and reflective of timely updates. Sometimes these updates break convention with past versions and some quirky behavior can arise. One such quirk is seen in the syntax used to install apps.

As of Django 3.2, the syntax for installing an application is appname.apps.AppnameConfig as opposed to previous versions where a simple appname would suffice. Let’s take a quick look at the difference. First, let’s define our project structure:

DjangoProject
  bestapp
    migrations
    __init__.py
    admin.py
    apps.py
    models.py
    tests.py
    views.py
  DjangoProject
    __init__.py
    asgi.py
    settings.py
    urls.py
    wsgi.py
  templates
  manage.py

Here we see boilerplate Django project structure with a single app having been installed via the manage.py startapp bestapp command. Among other files, this generates the bestapp/apps.py file with the following information:

from django.apps import AppConfig


class BestappConfig(AppConfig):
    default_auto_field = 'django.db.models.BigAutoField'
    name = 'bestapp'

Now we are ready to consider how to install this app into our Django project. As outlined in the documentation, for this version and previous versions as well, this is done by adding our app name via the DjangoProject/settings.py file in the following line:

INSTALLED_APPS = [
    'django.contrib.admin',
    'django.contrib.auth',
    'django.contrib.contenttypes',
    'django.contrib.sessions',
    'django.contrib.messages',
    'django.contrib.staticfiles',
    OUR APP GOES HERE
]

Old Syntax

In previous versions of Django apps were installed simply by adding their name into the INSTALLED_APPS list with very little specificity as to how those apps’ configuration was selected. This was done via the following syntax:

INSTALLED_APPS = [
    'django.contrib.admin',
    'django.contrib.auth',
    'django.contrib.contenttypes',
    'django.contrib.sessions',
    'django.contrib.messages',
    'django.contrib.staticfiles',
    'bestapp'
]

The simple addition of 'bestapp' was enough to inform Django of our new app’s presence and inclusion in our project assets. This is no longer the syntax and will result in the following error:

django.core.exceptions.ImproperlyConfigured: Cannot import 'bestapp'. Check that 'bestapp.apps.CoreConfig.name' is correct.

New Syntax

As of Django 3.x the syntax for adding applications has changed. As outlined in the official documentation, the new syntax is as follows:

INSTALLED_APPS = [
    'bestapp.apps.BestappConfig',
    'django.contrib.admin',
    'django.contrib.auth',
    'django.contrib.contenttypes',
    'django.contrib.sessions',
    'django.contrib.messages',
    'django.contrib.staticfiles',
]

With this, running the migrate or makemigrations command will work as expected—unless of course there is some other error lurking.

Apps in Subdirectories

The new syntax also requires some updating the /apps.py file for any applications installed in subdirectory locations. Consider the following app install location:

.
└── DjangoProject/
    └── Apps/
        ├── bestapp/
        │   ├── migrations
        │   ├── __init__.py
        │   ├── admin.py
        │   ├── apps.py
        │   ├── models.py
        │   ├── tests.py
        │   └── views.py
        └── ...

In this project structure, it is now required to update the Apps/bestapp/apps.py file to reflect the following format:

from django.apps import AppConfig


class BestappConfig(AppConfig):
    default_auto_field = 'django.db.models.BigAutoField'
    name = 'Apps.bestapp'  # <------------- added 'Apps' (old version was name='bestapp')

Final Thoughts

This syntactic shift can cause a headache to be sure. For those used to the old syntax—the one that was used forever—it can take a while before realizing such a change has been made. This can cause hiccups when updating Django versions or in starting new projects using the latest version.

Zαck West
Full-Stack Software Engineer with 10+ years of experience. Expertise in developing distributed systems, implementing object-oriented models with a focus on semantic clarity, driving development with TDD, enhancing interfaces through thoughtful visual design, and developing deep learning agents.