Search code examples
djangoamazon-s3django-staticfilescookiecutter-django

Static Files not saving on S3 bucket using cookiecutter-django


I'm trying to deploy my project on Heroku. I ran heroku run python3 manage.py collectstatic after deploying it.

I have this on config/base.py

STATIC_ROOT = str(ROOT_DIR("staticfiles"))
STATIC_URL = "/static/"
STATICFILES_DIRS = [str(APPS_DIR.path("static"))]
STATICFILES_FINDERS = [
    "django.contrib.staticfiles.finders.FileSystemFinder",
    "django.contrib.staticfiles.finders.AppDirectoriesFinder",
]

This is on the config/production.py

BASE_DIR = os.path.dirname(os.path.dirname(os.path.abspath(__file__)))
INSTALLED_APPS += ["storages"]  # noqa F405
AWS_ACCESS_KEY_ID = env("DJANGO_AWS_ACCESS_KEY_ID")
AWS_SECRET_ACCESS_KEY = env("DJANGO_AWS_SECRET_ACCESS_KEY")
AWS_STORAGE_BUCKET_NAME = env("DJANGO_AWS_STORAGE_BUCKET_NAME")
AWS_QUERYSTRING_AUTH = False
_AWS_EXPIRY = 60 * 60 * 24 * 7
AWS_S3_OBJECT_PARAMETERS = {
"CacheControl": f"max-age={_AWS_EXPIRY}, s-maxage={_AWS_EXPIRY}, must-revalidate"
}
AWS_DEFAULT_ACL = None
AWS_S3_REGION_NAME = env("DJANGO_AWS_S3_REGION_NAME", default=None)
STATICFILES_STORAGE = "whitenoise.storage.CompressedManifestStaticFilesStorage"

from storages.backends.s3boto3 import S3Boto3Storage  # noqa E402


class StaticRootS3Boto3Storage(S3Boto3Storage):
    location = "static"
    default_acl = "public-read"


class MediaRootS3Boto3Storage(S3Boto3Storage):
    location = "media"
    file_overwrite = False

DEFAULT_FILE_STORAGE = "config.settings.production.MediaRootS3Boto3Storage"
MEDIA_URL = f"https://{AWS_STORAGE_BUCKET_NAME}.s3.amazonaws.com/media/"

These are my heroku env variables enter image description here

I generated this using cookiecutter-django. Everything works fine on my localhost but when I deploy it to heroku, it doesn't save the static files.


Solution

  • Instead of uploading the assets to S3, it could be easier to use whitenoise to serve the static files. Basically whitenoise allows you to serve the static files from your django app instead of somewhere else.

    Install whitenoise with pip install. pip install whitenoise.

    You'll need to include whitenoise as a middleware.

    MIDDLEWARE = [
      'django.middleware.security.SecurityMiddleware',
      'whitenoise.middleware.WhiteNoiseMiddleware',
      # ...
    ]
    

    To use whitenoise in development mode. You need an installed app.

    INSTALLED_APPS = [
        'whitenoise.runserver_nostatic',
        'django.contrib.staticfiles',
        # ...
    ]
    

    That's about it! You can read more about in the documentation. http://whitenoise.evans.io/en/stable/django.html

    For more performance you can configure it to use a CDN, but if it's just a small site, that's not necessary.