Applications
Django contains a registry of installed applications that stores configurationand provides introspection. It also maintains a list of available models.
This registry is called apps
and it’s available indjango.apps
:
- >>> from django.apps import apps
- >>> apps.get_app_config('admin').verbose_name
- 'Administration'
Projects and applications
The term project describes a Django web application. The project Pythonpackage is defined primarily by a settings module, but it usually containsother things. For example, when you run django-admin startproject mysite
you’ll get a mysite
project directory that contains a mysite
Pythonpackage with settings.py
, urls.py
, and wsgi.py
. The project packageis often extended to include things like fixtures, CSS, and templates whicharen’t tied to a particular application.
A project’s root directory (the one that contains manage.py
) is usuallythe container for all of a project’s applications which aren’t installedseparately.
The term application describes a Python package that provides some set offeatures. Applications may be reused in variousprojects.
Applications include some combination of models, views, templates, templatetags, static files, URLs, middleware, etc. They’re generally wired intoprojects with the INSTALLED_APPS
setting and optionally with othermechanisms such as URLconfs, the MIDDLEWARE
setting, or templateinheritance.
It is important to understand that a Django application is a set of codethat interacts with various parts of the framework. There’s no such thing asan Application
object. However, there’s a few places where Django needs tointeract with installed applications, mainly for configuration and also forintrospection. That’s why the application registry maintains metadata in anAppConfig
instance for each installed application.
There’s no restriction that a project package can’t also be considered anapplication and have models, etc. (which would require adding it toINSTALLED_APPS
).
Configuring applications
To configure an application, subclass AppConfig
and putthe dotted path to that subclass in INSTALLED_APPS
.
When INSTALLED_APPS
contains the dotted path to an applicationmodule, Django checks for a default_app_config
variable in that module.
If it’s defined, it’s the dotted path to the AppConfig
subclass for that application.
If there is no default_app_config
, Django uses the baseAppConfig
class.
default_app_config
allows applications that predate Django 1.7 such asdjango.contrib.admin
to opt-in to AppConfig
featureswithout requiring users to update their INSTALLED_APPS
.
New applications should avoid default_app_config
. Instead they shouldrequire the dotted path to the appropriate AppConfig
subclass to be configured explicitly in INSTALLED_APPS
.
For application authors
If you’re creating a pluggable app called “Rock ’n’ roll”, here’s how youwould provide a proper name for the admin:
- # rock_n_roll/apps.py
- from django.apps import AppConfig
- class RockNRollConfig(AppConfig):
- name = 'rock_n_roll'
- verbose_name = "Rock ’n’ roll"
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'
That will cause RockNRollConfig
to be used when INSTALLED_APPS
contains 'rock_n_roll'
. This allows you to make use ofAppConfig
features without requiring your users to updatetheir INSTALLED_APPS
setting. Besides this use case, it’s best toavoid using default_app_config
and instead specify the app config class inINSTALLED_APPS
as described next.
Of course, you can also tell your users to put'rock_n_roll.apps.RockNRollConfig'
in their INSTALLED_APPS
setting. You can even provide several differentAppConfig
subclasses with different behaviors and allowyour users to choose one via their INSTALLED_APPS
setting.
The recommended convention is to put the configuration class in a submodule ofthe application called apps
. However, this isn’t enforced by Django.
You must include the name
attribute for Djangoto determine which application this configuration applies to. You can defineany attributes documented in the AppConfig
APIreference.
Note
If your code imports the application registry in an application’sinit.py
, the name apps
will clash with the apps
submodule.The best practice is to move that code to a submodule and import it. Aworkaround is to import the registry under a different name:
- from django.apps import apps as django_apps
For application users
If you’re using “Rock ’n’ roll” in a project called anthology
, but youwant it to show up as “Jazz Manouche” instead, you can provide your ownconfiguration:
- # anthology/apps.py
- from rock_n_roll.apps import RockNRollConfig
- class JazzManoucheConfig(RockNRollConfig):
- verbose_name = "Jazz Manouche"
- # anthology/settings.py
- INSTALLED_APPS = [
- 'anthology.apps.JazzManoucheConfig',
- # ...
- ]
Again, defining project-specific configuration classes in a submodule calledapps
is a convention, not a requirement.
Application configuration
- class
AppConfig
[source] - Application configuration objects store metadata for an application. Someattributes can be configured in
AppConfig
subclasses. Others are set by Django and read-only.
Configurable attributes
This attribute defines which application the configuration applies to. Itmust be set in all AppConfig
subclasses.
It must be unique across a Django project.
This attribute allows relabeling an application when two applicationshave conflicting labels. It defaults to the last component of name
.It should be a valid Python identifier.
It must be unique across a Django project.
This attribute defaults to label.title()
.
AppConfig.
path
- Filesystem path to the application directory, e.g.
'/usr/lib/pythonX.Y/dist-packages/django/contrib/admin'
.
In most cases, Django can automatically detect and set this, but you canalso provide an explicit override as a class attribute on yourAppConfig
subclass. In a few situations this isrequired; for instance if the app package is a namespace package withmultiple paths.
Read-only attributes
AppConfig.
module
Root module for the application, e.g.
<module 'django.contrib.admin' from'django/contrib/admin/init.py'>
.- Module containing the models, e.g.
<module 'django.contrib.admin.models'from 'django/contrib/admin/models.py'>
.
It may be None
if the application doesn’t contain a models
module.Note that the database related signals such aspre_migrate
andpost_migrate
are only emitted for applications that have a models
module.
Methods
Requires the app registry to be fully populated.
AppConfig.
getmodel
(_model_name, require_ready=True)[source]- Returns the
Model
with the givenmodel_name
.model_name
is case-insensitive.
Raises LookupError
if no such model exists in this application.
Requires the app registry to be fully populated unless therequire_ready
argument is set to False
. require_ready
behavesexactly as in apps.get_model()
.
AppConfig.
ready
()[source]- Subclasses can override this method to perform initialization tasks suchas registering signals. It is called as soon as the registry is fullypopulated.
Although you can’t import models at the module-level whereAppConfig
classes are defined, you can import them inready()
, using either an import
statement orget_model()
.
If you’re registering model signals
, youcan refer to the sender by its string label instead of using the modelclass itself.
Example:
- from django.db.models.signals import pre_save
- def ready(self):
- # importing model classes
- from .models import MyModel # or...
- MyModel = self.get_model('MyModel')
- # registering signals with the model's string label
- pre_save.connect(receiver, sender='app_label.MyModel')
Warning
Although you can access model classes as described above, avoidinteracting with the database in your ready()
implementation.This includes model methods that execute queries(save()
,delete()
, manager methods etc.), andalso raw SQL queries via django.db.connection
. Yourready()
method will run during startup of every managementcommand. For example, even though the test database configuration isseparate from the production settings, manage.py test
would stillexecute some queries against your production database!
Note
In the usual initialization process, the ready
method is only calledonce by Django. But in some corner cases, particularly in tests whichare fiddling with installed applications, ready
might be called morethan once. In that case, either write idempotent methods, or put a flagon your AppConfig
classes to prevent re-running code which shouldbe executed exactly one time.
Namespace packages as apps
Python packages without an init.py
file are known as “namespacepackages” and may be spread across multiple directories at different locationson sys.path
(see PEP 420).
Django applications require a single base filesystem path where Django(depending on configuration) will search for templates, static assets,etc. Thus, namespace packages may only be Django applications if one of thefollowing is true:
- The namespace package actually has only a single location (i.e. is notspread across more than one directory.)
- The
AppConfig
class used to configure the applicationhas apath
class attribute, which is theabsolute directory path Django will use as the single base path for theapplication.If neither of these conditions is met, Django will raiseImproperlyConfigured
.
Application registry
apps
The application registry provides the following public API. Methods thataren’t listed below are considered private and may change without notice.
Boolean attribute that is set to
True
after the registry is fullypopulated and allAppConfig.ready()
methods are called.Returns an iterable of
AppConfig
instances.Returns an
AppConfig
for the application with thegivenapp_label
. RaisesLookupError
if no such applicationexists.Checks whether an application with the given name exists in the registry.
app_name
is the full name of the app, e.g.'django.contrib.admin'
.- Returns the
Model
with the givenapp_label
andmodel_name
. As a shortcut, this method also accepts a singleargument in the formapp_label.model_name
.model_name
iscase-insensitive.
Raises LookupError
if no such application or model exists. RaisesValueError
when called with a single argument that doesn’t containexactly one dot.
Requires the app registry to be fully populated unless therequire_ready
argument is set to False
.
Setting require_ready
to False
allows looking up modelswhile the app registry is being populated,specifically during the second phase where it imports models. Thenget_model()
has the same effect as importing the model. The main usecase is to configure model classes with settings, such asAUTH_USER_MODEL
.
When require_ready
is False
, get_model()
returns a model classthat may not be fully functional (reverse accessors may be missing, forexample) until the app registry is fully populated. For this reason, it’sbest to leave require_ready
to the default value of True
wheneverpossible.
Initialization process
How applications are loaded
When Django starts, django.setup()
is responsible for populating theapplication registry.
setup
(set_prefix=True)[source]Configures Django by:
- Loading the settings.
- Setting up logging.
- If
set_prefix
is True, setting the URL resolver script prefix toFORCE_SCRIPT_NAME
if defined, or/
otherwise. Initializing the application registry.This function is called automatically:
When running an HTTP server via Django’s WSGI support.
- When invoking a management command.It must be called explicitly in other cases, for instance in plain Pythonscripts.
The application registry is initialized in three stages. At each stage, Djangoprocesses all applications in the order of INSTALLED_APPS
.
- First Django imports each item in
INSTALLED_APPS
.
If it’s an application configuration class, Django imports the root packageof the application, defined by its name
attribute. Ifit’s a Python package, Django creates a default application configuration.
At this stage, your code shouldn’t import any models!
In other words, your applications’ root packages and the modules thatdefine your application configuration classes shouldn’t import any models,even indirectly.
Strictly speaking, Django allows importing models once their applicationconfiguration is loaded. However, in order to avoid needless constraints onthe order of INSTALLED_APPS
, it’s strongly recommended notimport any models at this stage.
Once this stage completes, APIs that operate on application configurationssuch as get_app_config()
become usable.
- Then Django attempts to import the
models
submodule of each application,if there is one.
You must define or import all models in your application’s models.py
ormodels/init.py
. Otherwise, the application registry may not be fullypopulated at this point, which could cause the ORM to malfunction.
Once this stage completes, APIs that operate on models such asget_model()
become usable.
- Finally Django runs the
ready()
method of each applicationconfiguration.
Troubleshooting
Here are some common problems that you may encounter during initialization:
AppRegistryNotReady
: This happens whenimporting an application configuration or a models module triggers code thatdepends on the app registry.
For example, gettext()
uses the appregistry to look up translation catalogs in applications. To translate atimport time, you need gettext_lazy()
instead. (Using gettext()
would be a bug,because the translation would happen at import time, rather than at eachrequest depending on the active language.)
Executing database queries with the ORM at import time in models moduleswill also trigger this exception. The ORM cannot function properly until allmodels are available.
This exception also happens if you forget to call django.setup()
ina standalone Python script.
ImportError: cannot import name …
This happens if the import sequenceends up in a loop.
To eliminate such problems, you should minimize dependencies between yourmodels modules and do as little work as possible at import time. To avoidexecuting code at import time, you can move it into a function and cache itsresults. The code will be executed when you first need its results. Thisconcept is known as “lazy evaluation”.
django.contrib.admin
automatically performs autodiscovery ofadmin
modules in installed applications. To prevent it, change yourINSTALLED_APPS
to contain'django.contrib.admin.apps.SimpleAdminConfig'
instead of'django.contrib.admin'
.