Search code examples
djangoamazon-web-servicesaws-lambdadjango-contrib

messages not appearing in admin on AWS dev server Django-3.1


context: Django 3.1 app deployed to a AWS lambda with terraform. I have not set up my production settings yet, this is my dev server.

I'm using https://github.com/adamchainz/apig-wsgi

I noticed that messages from django.contrib.messages don't appear when attempting to get the api key with djangorestframework-api-key via the admin. It being on the lambda means I'm unable to access the lambda REPL to create the api key programmatically.

note: django-debug-toolbar also does not work and does so quietly, so I have a sneaking suspicion my context_processors settings are off so I don't have messages or DEBUG variables but I can't find the issue in my settings?? Below is my code without debug toolbar settings.

project/settings/base.py

DEBUG = True 

INSTALLED_APPS = [
    'app',

    'rest_framework',
    'rest_framework_api_key',

    'django.contrib.admin',
    'django.contrib.auth',
    'django.contrib.contenttypes',
    'django.contrib.sessions',
    'django.contrib.messages',
    'django.contrib.staticfiles',
]

MIDDLEWARE = [
    'django.middleware.security.SecurityMiddleware',
    'django.contrib.sessions.middleware.SessionMiddleware',
    'django.middleware.common.CommonMiddleware',
    'django.middleware.csrf.CsrfViewMiddleware',
    'django.contrib.auth.middleware.AuthenticationMiddleware',
    'django.contrib.messages.middleware.MessageMiddleware',
    'django.middleware.clickjacking.XFrameOptionsMiddleware',
]

TEMPLATES = [
    {
        'BACKEND': 'django.template.backends.django.DjangoTemplates',
        'DIRS': [
            os.path.join(BASE_DIR, 'templates'),
        ],
        'APP_DIRS': True,
        'OPTIONS': {
            'context_processors': [
                'django.template.context_processors.debug',
                'django.template.context_processors.request',
                'django.contrib.auth.context_processors.auth',
                'django.contrib.messages.context_processors.messages',
            ],
        },
    },
]

STATICFILES_FINDERS = [
    'django.contrib.staticfiles.finders.AppDirectoriesFinder',
]

STATICFILES_STORAGE = 'storages.backends.s3boto3.S3StaticStorage'

AWS_STORAGE_BUCKET_NAME= [redacted]

AWS_DEFAULT_ACL = [redacted]
AWS_QUERYSTRING_AUTH= [redacted]
AWS_S3_REGION_NAME = [redacted]
AWS_LOCATION = [redacted]

USE_I18N = True

STATIC_URL = '/static/'

REST_FRAMEWORK = {
...
    'DEFAULT_PERMISSION_CLASSES': [
        "rest_framework_api_key.permissions.HasAPIKey",
    ]
}

project/wsgi.py

import os

from django.core.wsgi import get_wsgi_application

os.environ.setdefault('DJANGO_SETTINGS_MODULE', 'project.settings')

application = get_wsgi_application()

lambda_function.py



def install_secrets():
    """Add the secrets from the secret named by ENV_SECRET_ID to os.environ"""
    import os
    secret_id = os.environ.get('ENV_SECRET_ID')
    if not secret_id:
        return
        
    import boto3
    import json
    

    session = boto3.session.Session()
    client = session.client('secretsmanager')
    response = client.get_secret_value(SecretId=secret_id)
    overlay = json.loads(response['SecretString'])
    os.environ.update(overlay)
    

def manage(event, context):
    """Entry point for running a management command. Supported formats:

    - "migrate!"
    - ["migrate"]
    - {"command": ["migrate"]}
    """
    if isinstance(event, dict):
        command = event['command']
    else:
        command = event
    if isinstance(command, str):
        command = command.split()

    install_secrets()
    from django.core.wsgi import get_wsgi_application
    get_wsgi_application()  # Initialize Django
    from django.core import management
    return management.call_command(*command)


_real_handler = None


def lambda_handler(event, context):
    """Entry point for web requests"""
    global _real_handler

    if _real_handler is None:
        print('No Cache, getting secrets.')
        install_secrets()
        from apig_wsgi import make_lambda_handler
        from django.core.wsgi import get_wsgi_application
        os.environ.setdefault('DJANGO_SETTINGS_MODULE', 'mysite.settings')
        application = get_wsgi_application()
        _real_handler = make_lambda_handler(application)

    return _real_handler(event, context)

default admin template admin/base.html where I'm expecting messages to show up (its just looping through the messages object, shouldn't need any JS or CSS to appear): https://github.com/django/django/blob/2d8232fa716f5fe46eec9f35a0e90c2d0f126279/django/contrib/admin/templates/admin/base.html#L82

        {% block messages %}
          {% if messages %}
            <ul class="messagelist">{% for message in messages %}
              <li{% if message.tags %} class="{{ message.tags }}"{% endif %}>{{ message|capfirst }}</li>
            {% endfor %}</ul>
          {% endif %}
        {% endblock messages %}

requirements.txt

Django>=3.1,<3.2
django-storages==1.11.1
apig-wsgi
psycopg2-binary
djangorestframework
djangorestframework-api-key==2.1.0

attempts:

  • tried hard reload F5 and all that
  • tried adding django debug toolbar and logging the apikey that shows up in messages in the admin, but didn't work because toolbar also doesn't show up (not shown in code above)
  • tried collectstatic on dev server
  • tried checking user sessions and seeing the messages on user sessions and there are messages there

Solution

  • A talented colleague fixed this. Adding

    MESSAGE_STORAGE = 'django.contrib.messages.storage.session.SessionStorage'
    

    to your settings resolves the issue.

    Credit goes to https://stackoverflow.com/users/1394697/flipperpa