Opened 4 years ago

Closed 4 years ago

#32186 closed Bug (duplicate)

Application's `ready()` method doesn't called when app's author missed to define `default_app_config`

Reported by: Anthony Owned by: nobody
Component: Core (Other) Version: 3.1
Severity: Normal Keywords:
Cc: Triage Stage: Unreviewed
Has patch: no Needs documentation: no
Needs tests: no Patch needs improvement: no
Easy pickings: no UI/UX: no

Description

I think, the issue is applied to documentation specifically, but the code can do better too.

If application is referenced in INSTALLED_APPS by package path rather than AppConfigs sublcass path, and application's author missed to define default_app_config, then application's initialization will be skipped silently. It leads to hard-to-debug bugs, especially with things that already hard-to-debug such as scheduling asynchronous jobs with signals.

Details

In Applications documentation page, it is stated that application author need to provide subclass of AppConfig. Then, the user of application need to reference it in INSTALLED_APPS setting either by app's package path, or by AppConfig subclass.

It is also stated that app's author can make the loading of his AppConfig subclass by pointing default_app_config variable in __init__.py to AppConfig subclass full dotted path:

You can make your application load this AppConfig subclass by default as follows:

 # rock_n_roll/__init__.py

 default_app_config = 'rock_n_roll.apps.RockNRollConfig'

Note that is not "required", nor "should" - you just "can". I treat it as "you can, if you will".

Later on, it is stated that

AppConfig.ready()
Subclasses can override this method to perform initialization tasks such as registering signals.

And finally, in Signals documentation page, it is suggested to import application's signals in .ready() method.

It is fleetingly stated, though, in Configuring applications that:

If there is no default_app_config, Django uses the base AppConfig class

Which means that application author's AppConfig subclass will not even evaluated - so, nor .ready() is called, too.

The docs should explicitly warn (at least) an user that is is the case if app's author missed to define default_app_config, or user itself referenced application not by full AppConfig class.

The code

It can do better, too.

There is clear condition that custom AppConfig subclass is skipped, here:

        else:
            try:
                # If this works, the app module specifies an app config class.
                entry = module.default_app_config
            except AttributeError:
                # Otherwise, it simply uses the default app config class.
                return cls(entry, module)

github https://github.com/django/django/blob/stable/3.1.x/django/apps/config.py#L110

An user, again, should be explicitly warned (at least) that it is the case, for example with log event of WARNING level.

Silently ignoring such a crucial nuance is worst possible way. Users can (and will, in my experience) assume, for example, that subclassing AppConfig and overriding .ready() method is enough for registering their signals, which is far from truth. The solution could be to use full AppConfig paths, but seems like no one using it.

In our current project, there is about 30 installed apps (w/o our own), and none of them referenced by AppConfigs subclasses:

INSTALLED_APPS = [
    'polymorphic',
    'watchman',
    'django.contrib.auth',
    'django.contrib.contenttypes',
    'django.contrib.sessions',
    'django.contrib.messages',
    'collectfast',
    'django.contrib.staticfiles',
    'dal',
    'dal_select2',
    'dal_queryset_sequence',
    'django_admin_env_notice',
    'django.contrib.admin',
    'django.contrib.admindocs',
    'adminsortable2',
    'ckeditor',
    'ckeditor_uploader',
    'easy_pdf',
    'rest_framework',
    'django_filters',
    'djoser',
    'social_django',
    'rest_social_auth',
    'axes',
    'corsheaders',
    'drf_yasg',
    'django_extensions',
    'django.contrib.postgres',
    'psqlextra',
    'versatileimagefield',
]

The most popular reusable apps also suggest usage of just package path in their docs:

https://www.django-rest-framework.org/#installation
https://django-allauth.readthedocs.io/en/latest/installation.html#django
https://github.com/django-extensions/django-extensions#installing-it
https://github.com/adamchainz/django-cors-headers#setup

Change History (2)

comment:1 by Anthony, 4 years ago

Type: UncategorizedBug

comment:2 by Carlton Gibson, 4 years ago

Component: UncategorizedCore (Other)
Resolution: duplicate
Status: newclosed

This is a duplicate of #31180, which will have default app configs automatically discovered from Django 3.2.

Note: See TracTickets for help on using tickets.
Back to Top