#32186: Application's `ready()` method doesn't called when app's author missed
to
define `default_app_config`
-----------------------------------------+------------------------
Reporter: Anthony | Owner: nobody
Type: Uncategorized | Status: new
Component: Uncategorized | Version: 3.1
Severity: Normal | Keywords:
Triage Stage: Unreviewed | Has patch: 0
Needs documentation: 0 | Needs tests: 0
Patch needs improvement: 0 | Easy pickings: 0
UI/UX: 0 |
-----------------------------------------+------------------------
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 `AppConfig`s 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 [https://docs.djangoproject.com/en/2.2/ref/applications/#for-
application-authors "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".
[https://docs.djangoproject.com/en/3.1/ref/applications/#django.apps.AppConfig.ready
Later on], it is stated that
`AppConfig.ready()`
Subclasses can override this method to perform initialization tasks such
as registering signals.
And finally, in [https://docs.djangoproject.com/en/3.1/topics/signals
/#connecting-receiver-functions "Signals"] documentation page, it is
suggested to import application's signals in `.ready()` method.
It is fleetingly stated, though, in
[https://docs.djangoproject.com/en/3.1/ref/applications/#configuring-
applications "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
([https://stackoverflow.com/search?q=django+signals+not+working 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 `AppConfig`s 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
--
Ticket URL: <https://code.djangoproject.com/ticket/32186>
Django <https://code.djangoproject.com/>
The Web framework for perfectionists with deadlines.
--
You received this message because you are subscribed to the Google Groups
"Django updates" group.
To unsubscribe from this group and stop receiving emails from it, send an email
to [email protected].
To view this discussion on the web visit
https://groups.google.com/d/msgid/django-updates/050.cd2cfa91b0c3dfd68cbdae69770fe8f5%40djangoproject.com.