#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 django-updates+unsubscr...@googlegroups.com. To view this discussion on the web visit https://groups.google.com/d/msgid/django-updates/050.cd2cfa91b0c3dfd68cbdae69770fe8f5%40djangoproject.com.