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.
How Django finds its settings in Divio projects
Your change to
manage.pyallowed thecollectstaticexecuted by the Dockerfile:to find the settings correctly. In effect, you hard-coded the
DJANGO_SETTINGS_MODULEenvironment variable into themanage.py.This will allow any
manage.pycommand 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 webcommand 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_MODULEenvironment 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
collectstaticcommand 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.
The best solution
In fact you don't need to do either of these things. Instead of amending
manage.pyand customising the environment variable for each each environment, add: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.