Both can be used for third-party apps. The idea is that in order to use an app, you need to load the corresponding AppConfig.
Django has a mechanism to determine the AppConfig to use. If there is no subclass of AppConfig in the apps.py, then the default AppConfig is used for that application.
If there is a single subclass of AppConfig, then it will make use of that AppConfig. If there are multiple such subclasses, and one has default=True, then that will be the AppConfig that is used.
We can also specify a default AppConfig in the __init__.py of the app module, so then the __init__.py looks like:
# app_name/__init__.py
default_app_config = 'app_name.apps.AppConfigSubclass'
These are thus all used to determine the default AppConfig. It means that if you write the name of the app as an element of the INSTALLED_APPS setting [Django-doc], it is used to determine the default AppConfig to run this.
It is however sometimes necessary to run the application with another subclass of the AppConfig. In that case you specify the full qualified name of the AppConfig, so then the INSTALLED_APP looks like:
# settings.py
# …
INSTALLED_APPS = [
# …,
'app_name.apps.OtherAppConfig'
# …
]
# …
So as long as it is clear what the default app is, we can work with the name of the app. From the moment we need another AppConfig than the default one, it is necessary to specify that AppConfig.