I have my Django app settings in a folder within the app folder with an init.py and this works fine on my current VPS server, Pycharm development and in the Divio local development environment. However, when I try and deploy this to Divio staging I get "ModuleNotFoundError: No module named 'settings'". Why is this?
Manage.py:
#!/usr/bin/env python
import os
from aldryn_django import startup
if __name__ == "__main__":
os.environ.setdefault("DJANGO_SETTINGS_MODULE", "app.settings")
startup.manage(path=os.path.dirname(os.path.abspath(__file__)))
No settings.py file
Folder called settings with:
_ init _.py
from .dev_divio import * # or .dev if you want dev
from .common import *
INSTALLED_ADDONS = [
# <INSTALLED_ADDONS> # Warning: text inside the INSTALLED_ADDONS tags is auto-generated. Manual changes will be overwritten.
'aldryn-addons',
'aldryn-django',
'aldryn-sso',
# </INSTALLED_ADDONS>
]
import aldryn_addons.settings
aldryn_addons.settings.load(locals())
# Application definition
INSTALLED_APPS.extend([
# add your project specific apps here
# 'django.contrib.admin',
# 'django.contrib.auth',
# 'django.contrib.contenttypes',
# 'django.contrib.sessions',
# 'django.contrib.messages',
# 'django.contrib.staticfiles',
# 'django.contrib.sites',
'rest_framework',
'rest_framework.authtoken',
'appname',
])
which imports:
common.py dev_divio.py
The two files above have the config in.
You were nearly there.
Your change to manage.py
allowed the collectstatic
executed by the Dockerfile:
RUN DJANGO_MODE=build python manage.py collectstatic --noinput
to find the settings correctly. In effect, you hard-coded the DJANGO_SETTINGS_MODULE
environment variable into the manage.py
.
This will allow any manage.py
command to find the settings, so (as you discovered) you'd be able to run the site locally.
However, other commands also need to know where the settings are, such as the start web
command that is used in Cloud deployments, or locally if you run the local server in live configuration.
These commands rely on a correctly-set DJANGO_SETTINGS_MODULE
environment variable, and that can be set locally in .env-local
, or for Cloud servers using the Environment variables view in the Control Panel.
However, environment variables set this way will only be available when containers are launched from an image that has already been built. They will not be available for the collectstatic
command that's in the Dockerfile, because at this stage the image is being built.
It's inelegant to have to provide the same information twice, and especially to hard-code an environment variable in a Python module.
In fact you don't need to do either of these things. Instead of amending manage.py
and customising the environment variable for each each environment, add:
ENV DJANGO_SETTINGS_MODULE=app.settings
to the Dockerfile (before any Django commands are executed).
This will make the variable immediately available, and will also bake it into the image, so that each container that is created from it will contain that variable by default.
Variables set this way can still be overridden on a per-environment basis.