Django: ImproperlyConfigured: The SECRET_KEY setting must not be empty

184,417

Solution 1

I had the same error and it turned out to be a circular dependency between a module or class loaded by the settings and the settings module itself. In my case it was a middleware class which was named in the settings which itself tried to load the settings.

Solution 2

I ran into the same problem after restructuring the settings as per the instructions from Daniel Greenfield's book Two scoops of Django.

I resolved the issue by setting

os.environ.setdefault("DJANGO_SETTINGS_MODULE", "project_name.settings.local")

in manage.py and wsgi.py.

Update:

In the above solution, local is the file name (settings/local.py) inside my settings folder, which holds the settings for my local environment.

Another way to resolve this issue is to keep all your common settings inside settings/base.py and then create 3 separate settings files for your production, staging and dev environments.

Your settings folder will look like:

settings/
    __init__.py
    base.py
    local.py
    prod.py
    stage.py

and keep the following code in your settings/__init__.py

from .base import *

env_name = os.getenv('ENV_NAME', 'local')

if env_name == 'prod':
    from .prod import *
elif env_name == 'stage':
    from .stage import *
else:
    from .local import *

Solution 3

Remove .pyc files

Ubuntu terminal command for deleting .pyc : find . -name "*.pyc" -exec rm -rf {} \;

I have got same error when I did python manage.py runserver. It was because .pyc file. I deleted .pyc file from project directory then it was working.

Solution 4

I hadn't specified the settings file:

python manage.py runserver --settings=my_project.settings.develop

Solution 5

I had the same problem with Celery. My setting.py before:

SECRET_KEY = os.environ.get('DJANGO_SECRET_KEY')

after:

SECRET_KEY = os.environ.get('DJANGO_SECRET_KEY', <YOUR developing key>)

If the environment variables are not defined then: SECRET_KEY = YOUR developing key

Share:
184,417
clime
Author by

clime

Updated on November 17, 2021

Comments

  • clime
    clime over 2 years

    I am trying to set up multiple setting files (development, production, ..) that include some base settings. Cannot succeed though. When I try to run ./manage.py runserver I am getting the following error:

    (cb)clime@den /srv/www/cb $ ./manage.py runserver
    ImproperlyConfigured: The SECRET_KEY setting must not be empty.
    

    Here is my settings module:

    (cb)clime@den /srv/www/cb/cb/settings $ ll
    total 24
    -rw-rw-r--. 1 clime clime 8230 Oct  2 02:56 base.py
    -rw-rw-r--. 1 clime clime  489 Oct  2 03:09 development.py
    -rw-rw-r--. 1 clime clime   24 Oct  2 02:34 __init__.py
    -rw-rw-r--. 1 clime clime  471 Oct  2 02:51 production.py
    

    Base settings (contain SECRET_KEY):

    (cb)clime@den /srv/www/cb/cb/settings $ cat base.py:
    # Django base settings for cb project.
    
    import django.conf.global_settings as defaults
    
    DEBUG = False
    TEMPLATE_DEBUG = False
    
    INTERNAL_IPS = ('127.0.0.1',)
    
    ADMINS = (
        ('clime', '[email protected]'),
    )
    
    MANAGERS = ADMINS
    
    DATABASES = {
        'default': {
            #'ENGINE': 'django.db.backends.postgresql_psycopg2', # Add 'postgresql_psycopg2', 'mysql', 'sqlite3' or 'oracle'.
            'ENGINE': 'django.db.backends.postgresql_psycopg2',
            'NAME': 'cwu',                   # Or path to database file if using sqlite3.
            'USER': 'clime',                 # Not used with sqlite3.
            'PASSWORD': '',                  # Not used with sqlite3.
            'HOST': '',                      # Set to empty string for localhost. Not used with sqlite3.
            'PORT': '',                      # Set to empty string for default. Not used with sqlite3.
        }
    }
    
    # Local time zone for this installation. Choices can be found here:
    # http://en.wikipedia.org/wiki/List_of_tz_zones_by_name
    # although not all choices may be available on all operating systems.
    # In a Windows environment this must be set to your system time zone.
    TIME_ZONE = 'Europe/Prague'
    
    # Language code for this installation. All choices can be found here:
    # http://www.i18nguy.com/unicode/language-identifiers.html
    LANGUAGE_CODE = 'en-us'
    
    SITE_ID = 1
    
    # If you set this to False, Django will make some optimizations so as not
    # to load the internationalization machinery.
    USE_I18N = False
    
    # If you set this to False, Django will not format dates, numbers and
    # calendars according to the current locale.
    USE_L10N = False # TODO: make this true and accustom date time input
    
    DATE_INPUT_FORMATS = defaults.DATE_INPUT_FORMATS + ('%d %b %y', '%d %b, %y') # + ('25 Oct 13', '25 Oct, 13')
    
    # If you set this to False, Django will not use timezone-aware datetimes.
    USE_TZ = True
    
    # Absolute filesystem path to the directory that will hold user-uploaded files.
    # Example: "/home/media/media.lawrence.com/media/"
    MEDIA_ROOT = '/srv/www/cb/media'
    
    # URL that handles the media served from MEDIA_ROOT. Make sure to use a
    # trailing slash.
    # Examples: "http://media.lawrence.com/media/", "http://example.com/media/"
    MEDIA_URL = '/media/'
    
    # Absolute path to the directory static files should be collected to.
    # Don't put anything in this directory yourself; store your static files
    # in apps' "static/" subdirectories and in STATICFILES_DIRS.
    # Example: "/home/media/media.lawrence.com/static/"
    STATIC_ROOT = '/srv/www/cb/static'
    
    # URL prefix for static files.
    # Example: "http://media.lawrence.com/static/"
    STATIC_URL = '/static/'
    
    # Additional locations of static files
    STATICFILES_DIRS = (
        # Put strings here, like "/home/html/static" or "C:/www/django/static".
        # Always use forward slashes, even on Windows.
        # Don't forget to use absolute paths, not relative paths.
    )
    
    # List of finder classes that know how to find static files in
    # various locations.
    STATICFILES_FINDERS = (
        'django.contrib.staticfiles.finders.FileSystemFinder',
        'django.contrib.staticfiles.finders.AppDirectoriesFinder',
    #    'django.contrib.staticfiles.finders.DefaultStorageFinder',
    )
    
    # Make this unique, and don't share it with anybody.
    SECRET_KEY = '8lu*6g0lg)9z!ba+a$ehk)xt)x%rxgb$i1&amp;022shmi1jcgihb*'
    
    # List of callables that know how to import templates from various sources.
    TEMPLATE_LOADERS = (
        'django.template.loaders.filesystem.Loader',
        'django.template.loaders.app_directories.Loader',
    #     'django.template.loaders.eggs.Loader',
    )
    
    TEMPLATE_CONTEXT_PROCESSORS = (
        'django.contrib.auth.context_processors.auth',
        'django.core.context_processors.request',
        'django.core.context_processors.debug',
        'django.core.context_processors.i18n',
        'django.core.context_processors.media',
        'django.core.context_processors.static',
        'django.core.context_processors.tz',
        'django.contrib.messages.context_processors.messages',
        'web.context.inbox',
        'web.context.base',
        'web.context.main_search',
        'web.context.enums',
    )
    
    MIDDLEWARE_CLASSES = (
        'django.middleware.common.CommonMiddleware',
        'django.contrib.sessions.middleware.SessionMiddleware',
        'django.middleware.csrf.CsrfViewMiddleware',
        'django.contrib.auth.middleware.AuthenticationMiddleware',
        'django.contrib.messages.middleware.MessageMiddleware',
        'watson.middleware.SearchContextMiddleware',
        'debug_toolbar.middleware.DebugToolbarMiddleware',
        'middleware.UserMemberMiddleware',
        'middleware.ProfilerMiddleware',
        'middleware.VaryOnAcceptMiddleware',
        # Uncomment the next line for simple clickjacking protection:
        # 'django.middleware.clickjacking.XFrameOptionsMiddleware',
    )
    
    ROOT_URLCONF = 'cb.urls'
    
    # Python dotted path to the WSGI application used by Django's runserver.
    WSGI_APPLICATION = 'cb.wsgi.application'
    
    TEMPLATE_DIRS = (
        # Put strings here, like "/home/html/django_templates" or "C:/www/django/templates".
        # Always use forward slashes, even on Windows.
        # Don't forget to use absolute paths, not relative paths.
        '/srv/www/cb/web/templates',
        '/srv/www/cb/templates',
    )
    
    INSTALLED_APPS = (
        'django.contrib.auth',
        'django.contrib.contenttypes',
        'django.contrib.sessions',
        'django.contrib.sites',
        'django.contrib.messages',
        'django.contrib.staticfiles',
        'south',
        'grappelli', # must be before admin
        'django.contrib.admin',
        'django.contrib.admindocs',
        'endless_pagination',
        'debug_toolbar',
        'djangoratings',
        'watson',
        'web',
    )
    
    AUTH_USER_MODEL = 'web.User'
    
    # A sample logging configuration. The only tangible logging
    # performed by this configuration is to send an email to
    # the site admins on every HTTP 500 error when DEBUG=False.
    # See http://docs.djangoproject.com/en/dev/topics/logging for
    # more details on how to customize your logging configuration.
    LOGGING = {
        'version': 1,
        'disable_existing_loggers': False,
        'filters': {
            'require_debug_false': {
                '()': 'django.utils.log.RequireDebugFalse'
            }
        },
        'formatters': {
            'standard': {
                'format' : "[%(asctime)s] %(levelname)s [%(name)s:%(lineno)s] %(message)s",
                'datefmt' : "%d/%b/%Y %H:%M:%S"
            },
        },
        'handlers': {
            'mail_admins': {
                'level': 'ERROR',
                'filters': ['require_debug_false'],
                'class': 'django.utils.log.AdminEmailHandler'
            },
            'null': {
                'level':'DEBUG',
                'class':'django.utils.log.NullHandler',
            },
            'logfile': {
                'level':'DEBUG',
                'class':'logging.handlers.RotatingFileHandler',
                'filename': "/srv/www/cb/logs/application.log",
                'maxBytes': 50000,
                'backupCount': 2,
                'formatter': 'standard',
            },
            'console':{
                'level':'INFO',
                'class':'logging.StreamHandler',
                'formatter': 'standard'
            },
        },
        'loggers': {
            'django.request': {
                'handlers': ['mail_admins'],
                'level': 'ERROR',
                'propagate': True,
            },
            'django': {
                'handlers':['console'],
                'propagate': True,
                'level':'WARN',
            },
            'django.db.backends': {
                'handlers': ['console'],
                'level': 'DEBUG',
                'propagate': False,
            },
            'web': {
                'handlers': ['console', 'logfile'],
                'level': 'DEBUG',
            },
        },
    }
    
    LOGIN_URL = 'login'
    LOGOUT_URL = 'logout'
    
    #ENDLESS_PAGINATION_LOADING = """
    #    <img src="/static/web/img/preloader.gif" alt="loading" style="margin:auto"/>
    #"""
    ENDLESS_PAGINATION_LOADING = """
        <div class="spinner small" style="margin:auto">
            <div class="block_1 spinner_block small"></div>
            <div class="block_2 spinner_block small"></div>
            <div class="block_3 spinner_block small"></div>
        </div>
    """
    
    DEBUG_TOOLBAR_CONFIG = {
        'INTERCEPT_REDIRECTS': False,
    }
    
    import django.template.loader
    django.template.loader.add_to_builtins('web.templatetags.cb_tags')
    django.template.loader.add_to_builtins('web.templatetags.tag_library')
    
    WATSON_POSTGRESQL_SEARCH_CONFIG = 'public.english_nostop'
    

    One of the setting files:

    (cb)clime@den /srv/www/cb/cb/settings $ cat development.py 
    from base import *
    
    DEBUG = True
    TEMPLATE_DEBUG = True
    
    ALLOWED_HOSTS = ['127.0.0.1', '31.31.78.149']
    
    DATABASES = {
        'default': {
            'ENGINE': 'django.db.backends.postgresql_psycopg2',
            'NAME': 'cwu',
            'USER': 'clime',
            'PASSWORD': '',
            'HOST': '',
            'PORT': '',
        }
    }
    
    MEDIA_ROOT = '/srv/www/cb/media/'
    
    STATIC_ROOT = '/srv/www/cb/static/'
    
    TEMPLATE_DIRS = (
        '/srv/www/cb/web/templates',
        '/srv/www/cb/templates',
    )
    

    Code in manage.py:

    (cb)clime@den /srv/www/cb $ cat manage.py 
    #!/usr/bin/env python
    import os
    import sys
    
    if __name__ == "__main__":
        os.environ.setdefault("DJANGO_SETTINGS_MODULE", "cb.settings.development")
    
        from django.core.management import execute_from_command_line
    
        execute_from_command_line(sys.argv)
    

    If I add from base import * into /srv/www/cb/cb/settings/__init__.py (which is otherwise empty), it magically starts to work but I don't understand why. Anyone could explain to me what's going on here? It must be some python module magic.

    EDIT: Everything also starts to work if I remove this line from base.py

    django.template.loader.add_to_builtins('web.templatetags.cb_tags')
    

    If I remove this line from web.templatetags.cb_tags, it also starts to work:

    from endless_pagination.templatetags import endless
    

    I guess it is because, in the end, it leads to

    from django.conf import settings
    PER_PAGE = getattr(settings, 'ENDLESS_PAGINATION_PER_PAGE', 10)
    

    So it creates some weird circular stuff and game over.

  • clime
    clime over 10 years
    sorry, I don't get your point. There was from base import * in at the beginning of development.py and it did not work.
  • Guilherme David da Costa
    Guilherme David da Costa over 10 years
    Oh sorry, I've jumped in regardless what was really happening. Django is still trying to import settings from settings instead of your development.py as it seems the reason of working when you import base at init.py
  • clime
    clime over 10 years
    Ye, I think the circularity does it.
  • HorseloverFat
    HorseloverFat about 10 years
    Do you know what the solution is then?
  • Sam Svenbjorgchristiensensen
    Sam Svenbjorgchristiensensen about 10 years
    Refactor to avoid circular dependency. The exact solution is really fairly specific to your own code.
  • ultraklon
    ultraklon about 10 years
    In my case as an example, I was calling # django-admin.py runserver that apparently imports the "settings.py" file in any of the directories included in the environment variable $PYTHONPATH and at the same time, in other environment variable $DJANGO_SETTINGS_MODULE i had "settings" as content, that apparently means it will try to include "settings" as a module. So what I did to solve this was, emptying $DJANGO_SETTINGS_MODULE with # export $DJANGO_SETTINGS_MODULE
  • Felix Böhme
    Felix Böhme over 8 years
    Hint: in order to identify what's causing the issue, e.g. add a random print statement in the settings file and move it around to see where it breaks.
  • Avinash Raj
    Avinash Raj over 8 years
    I didn't find an answer with this.
  • Bob Stein
    Bob Stein over 8 years
    This must be why so many django features work on either strings or objects. That must have resolved tons of circular dependencies. (I got this error by importing in settings.py.)
  • haky_nash
    haky_nash over 8 years
    Remove 'import haystack' from the top of your settings.py. Since you have django-haystack installed, it is already "available" to you. In the connection settings you can directly write haystack.backends... without explicitly importing it.
  • Hack-R
    Hack-R over 7 years
    This answer would be more useful if it were more specific... it says the problem is "something".
  • Srinivas Reddy Thatiparthy
    Srinivas Reddy Thatiparthy about 6 years
    find . -type f -name *.pyc -delete will do
  • Inyoka
    Inyoka over 5 years
    For anyone using Wagtail on PythonAnywhere just add the '.dev.' at the end of this line in WSGI ... os.environ['DJANGO_SETTINGS_MODULE'] = 'mysite.settings.dev' later you'll need to create a local.py outside of your source repo for your passwords etc.
  • Dev
    Dev almost 5 years
    Should be top answer
  • Trect
    Trect over 4 years
    ImportError: No module named local
  • Jinesh
    Jinesh over 4 years
    @Tessaracter use the name of the settings file you use instead of local. In my case, the local settings were kept in the file settings/local.py
  • Mayur
    Mayur over 4 years
    Perfect! Thanks.
  • Ariel
    Ariel about 4 years
    This violates Django conventions, replacing the properly documented DJANGO_SETTINGS_MODULE with a new custom environment variable that is not supported out of the box and has to be dealt with manually. I am surprised this has so many upvotes. I'm working on a project with this setup and we're running into a lot of problems, from difficulties in configuring an isolated environment for local development to external libraries breaking because they expect the DJANGO_SETTINGS_MODULE to work as expected and it doesn't.
  • Michael Stachura
    Michael Stachura over 3 years
    I've got same issue. Need to change > from django.utils.translation import gettext as _ to: > from django.utils.translation import gettext_lazy as _