Understanding Wagtail's settings files (base.py, dev.py, production.py, and local.py)
18 April 2025
Unlike Django, which, by default, generates a single settings.py
file, Wagtail generates three settings files—base.py
, dev.py
, and production.py
. In combination with a fourth, local.py
, which can be created manually if required, these files help manage settings configurations across different environments.
This post discusses the purpose of these files, the settings flow (hierarchy), and how to switch between settings environments.
The Wagtail settings
folder structure
By default, when creating a Wagtail project using the command wagtail start
, a folder structure is generated based upon Wagtail's standard project template. Within this structure, Wagtail generates a settings
folder like so:
(Note: The location of the settings
folder will vary depending upon the additional parameter given when running wagtail start
. For example, as shown here, wagtail start core
will create the settings
folder etc. inside a folder named core
).
lm/
├── core/
│ ├── settings/
│ │ ├── __init__.py
│ │ ├── base.py
│ │ ├── dev.py
│ │ └── production.py
│ ├── __init__.py
│ ├── apps.py
│ ├── urls.py
│ └── wsgi.py
└── manage.py
Purpose of the settings files
As outlined in the Wagtail documentation, each settings file serves a distinct role:
base.py
- Contains shared settings used in both development and production environments. Most configuration will likely reside here.
dev.py
- Contains settings specific to the development environment, such as features pertaining to debugging and local testing.
production.py
- Contains settings specific to the production environment, such as features pertaining to security and performance.
local.py
(optional, can be added if required)- Contains settings specific to a particular machine.
The settings flow (hierarchy)
By default, both dev.py
and production.py
begin by importing everything from base.py
:
from .base import *
and then end by trying to import everything from local.py
:
try:
from .local import *
except ImportError:
pass
As inferred, therefore, the default settings flow is:
dev.py
andproduction.py
import all settings frombase.py
dev.py
andproduction.py
then optionally override or add environment-specific settingsdev.py
andproduction.py
then try to import all settings fromlocal.py
, which has the final say in overriding any setting
Switching between settings environments
Django uses the DJANGO_SETTINGS_MODULE
environment variable to determine which settings file to load. As the Django documentation notes:
When you use Django, you have to tell it which settings you're using. Do this by using an environment variable, DJANGO_SETTINGS_MODULE
.
The value ofDJANGO_SETTINGS_MODULE
should be in Python path syntax, e.g.mysite.settings
. Note that the settings module should be on the Pythonsys.path
.
Consequently, for a Wagtail project named core
(such as that mentioned in the abridged tree shown earlier), it is necessary, in this case, to set the value of DJANGO_SETTINGS_MODULE
to one of the following settings environment module paths:
core.settings.dev
core.settings.production
Setting the DJANGO_SETTINGS_MODULE
environment variable
Default behaviour
Notably, Django/Wagtail attempts to set a default value for DJANGO_SETTINGS_MODULE
in two places (manage.py
and wsgi.py
), both via the same call to setdefault
:
os.environ.setdefault("DJANGO_SETTINGS_MODULE", "core.settings.dev")
However, as expected, setdefault
will only set a value once per key (in this case, DJANGO_SETTINGS_MODULE
). Therefore, if manage.py
is run first, for example via python manage.py runserver
, its DJANGO_SETTINGS_MODULE
value will be set but the value subsequently given in wsgi.py
will be ignored. Alternatively, for example on a production machine, if manage.py
is not run, the value given in wsgi.py
will be set.
Methods
The DJANGO_SETTINGS_MODULE
value can set in various ways, depending upon the context. The following are several, more common, methods for doing so.
Method 1
Edit either manage.py
or wsgi.py
, and modify the default value. For example:
# Change:
os.environ.setdefault("DJANGO_SETTINGS_MODULE", "core.settings.dev")
# to:
os.environ.setdefault("DJANGO_SETTINGS_MODULE", "core.settings.production")
Method 2
Again via code, set/override the value. For example:
os.environ["DJANGO_SETTINGS_MODULE"] = "core.settings.production"
Method 3
From the command line, use Django's --settings
flag when running manage.py
. For example:
python manage.py runserver --settings "core.settings.production"
Method 4
Again from the command line, export DJANGO_SETTINGS_MODULE
. For example:
export DJANGO_SETTINGS_MODULE=core.settings.production
python manage.py runserver
Method 5
Use an environment variable helper/manager. For example, store DJANGO_SETTINGS_MODULE
in a .env
file and then use python-dotenv to parse the file and load the key-value pair as an environment variable.
DJANGO_SETTINGS_MODULE=core.settings.production
#!/usr/bin/env python
import sys
from dotenv import load_dotenv
load_dotenv()
if __name__ == "__main__":
from django.core.management import execute_from_command_line
execute_from_command_line(sys.argv)