From b076c304e39682de3722ead9f763dea0e796a887 Mon Sep 17 00:00:00 2001 From: Jan Baykara Date: Fri, 16 Dec 2022 15:21:20 +0000 Subject: [PATCH] Configuration to allow static files to be hosted/served via S3 --- app/settings/production.py | 58 +++++++++++++++++++++++++++++--------- app/storage.py | 11 ++++++-- 2 files changed, 53 insertions(+), 16 deletions(-) diff --git a/app/settings/production.py b/app/settings/production.py index f92b8e77..3b91a55d 100644 --- a/app/settings/production.py +++ b/app/settings/production.py @@ -12,24 +12,54 @@ "redirect_to_non_www.middleware.RedirectToNonWww", ] +#### File storage -if os.getenv("AWS_S3_REGION_NAME"): - DEFAULT_FILE_STORAGE = "app.storage.DigitalOceanSpacesStorage" +# like `fra1` +AWS_S3_REGION_NAME = os.getenv("AWS_S3_REGION_NAME", None) +# like `leftbookclub` +AWS_STORAGE_BUCKET_NAME = os.getenv("AWS_STORAGE_BUCKET_NAME", None) +# like `https://fra1.digitaloceanspaces.com` +AWS_S3_ENDPOINT_URL = os.getenv("AWS_S3_ENDPOINT_URL", None) +AWS_ACCESS_KEY_ID = os.getenv("AWS_ACCESS_KEY_ID", None) +AWS_SECRET_ACCESS_KEY = os.getenv("AWS_SECRET_ACCESS_KEY", None) +# can be ignored +AWS_S3_CUSTOM_DOMAIN = os.getenv("AWS_S3_CUSTOM_DOMAIN", None) +# +USE_S3_FOR_STATIC_FILES = os.getenv("USE_S3_FOR_STATIC_FILES", "1") == "1" + +if AWS_S3_REGION_NAME is not None: AWS_S3_ADDRESSING_STYLE = "virtual" - # like `fra1` - AWS_S3_REGION_NAME = os.getenv("AWS_S3_REGION_NAME") - # like `leftbookclub` - AWS_STORAGE_BUCKET_NAME = os.getenv("AWS_STORAGE_BUCKET_NAME") - # like `https://fra1.digitaloceanspaces.com` - AWS_S3_ENDPOINT_URL = os.getenv("AWS_S3_ENDPOINT_URL") - AWS_ACCESS_KEY_ID = os.getenv("AWS_ACCESS_KEY_ID") - AWS_SECRET_ACCESS_KEY = os.getenv("AWS_SECRET_ACCESS_KEY") - # can be ignored - AWS_S3_CUSTOM_DOMAIN = os.getenv("AWS_S3_CUSTOM_DOMAIN") - MEDIA_URL = os.getenv("MEDIA_URL") + DEFAULT_FILE_STORAGE = "app.storage.DigitalOceanSpacesStorage" + ### Media + PUBLIC_MEDIA_LOCATION = "media" + MEDIA_URL = ( + ( + f"https://{AWS_S3_CUSTOM_DOMAIN}" + if AWS_S3_CUSTOM_DOMAIN + else AWS_S3_ENDPOINT_URL + ) + + "/" + + PUBLIC_MEDIA_LOCATION.lstrip("/").rstrip("/") + + "/" + ) + DEFAULT_FILE_STORAGE = "app.storage.MediaStorage" + ### Static + if USE_S3_FOR_STATIC_FILES: + STATIC_LOCATION = "static" + STATIC_URL = ( + ( + f"https://{AWS_S3_CUSTOM_DOMAIN}" + if AWS_S3_CUSTOM_DOMAIN + else AWS_S3_ENDPOINT_URL.rstrip("/") + ) + + "/" + + STATIC_LOCATION.lstrip("/").rstrip("/") + + "/" + ) + STATICFILES_STORAGE = "app.storage.StaticStorage" else: MEDIA_ROOT = os.getenv(MEDIA_ROOT) - MEDIA_URL = os.getenv("MEDIA_URL", "/media") + MEDIA_URL = os.getenv("MEDIA_URL", "/media/") if os.getenv("MAILJET_API_KEY"): diff --git a/app/storage.py b/app/storage.py index 579737ea..ddb473e6 100644 --- a/app/storage.py +++ b/app/storage.py @@ -1,9 +1,11 @@ import urllib.parse -from storages.backends.s3boto3 import S3Boto3Storage +from storages.backends.s3boto3 import S3Boto3Storage, S3ManifestStaticStorage -class DigitalOceanSpacesStorage(S3Boto3Storage): +class MediaStorage(S3Boto3Storage): + default_acl = "public-read" + def url(self, name, parameters=None, expire=None, http_method=None): s3_url = super().url(name, parameters, expire, http_method) @@ -31,3 +33,8 @@ def url(self, name, parameters=None, expire=None, http_method=None): fragment=url_parts.fragment, ) return url_parts.geturl() + + +class StaticStorage(S3ManifestStaticStorage): + location = "static" + default_acl = "public-read"