Opened 5 years ago
Closed 5 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 baseAppConfigclass
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 , 5 years ago
| Type: | Uncategorized → Bug |
|---|
comment:2 by , 5 years ago
| Component: | Uncategorized → Core (Other) |
|---|---|
| Resolution: | → duplicate |
| Status: | new → closed |
This is a duplicate of #31180, which will have default app configs automatically discovered from Django 3.2.