Repository: cookiecutter/cookiecutter-django

Issue:
Add Google Cloud Storage Option in addition to current AWS S3 options
I'm a big fan of this cookie cutter and find myself using it frequently for green field projects. 

Wondering if anyone would be interested in a pull-request to add Google compute cloud storage support for static and media files?

While AWS S3 is widely used, I find myself using the google ecosystem a bit more with the dockerized django cookie cutter.

One note is that these production dependencies would need to be updated boto==2.46.1 and django-storages==1.5.2

If this is a desirable addition, I can put together the PR and update the documentation etc.


Discussion:
I don't see how this could hurt. If you put together a PR, I can have a look at it.
@burhan Is this still open? I would like to give it a try.
I believe so, PR welcome
PR that offer additional options are always welcome. @-me if you need help with the PR.
An article explaining what changes are required:
https://ahhda.github.io/cloud/gce/django/2019/03/12/using-django-cookiecutter-cloud-storage.html

Resolving patch:
diff --git a/{{cookiecutter.project_slug}}/config/settings/production.py b/{{cookiecutter.project_slug}}/config/settings/production.py
--- a/{{cookiecutter.project_slug}}/config/settings/production.py
+++ b/{{cookiecutter.project_slug}}/config/settings/production.py
@@ -70,6 +70,7 @@
 # ------------------------------------------------------------------------------
 # https://django-storages.readthedocs.io/en/latest/#installation
 INSTALLED_APPS += ["storages"]  # noqa F405
+{% if cookiecutter.cloud_provider == 'AWS' %}
 # https://django-storages.readthedocs.io/en/latest/backends/amazon-S3.html#settings
 AWS_ACCESS_KEY_ID = env("DJANGO_AWS_ACCESS_KEY_ID")
 # https://django-storages.readthedocs.io/en/latest/backends/amazon-S3.html#settings
@@ -88,22 +89,27 @@
 AWS_DEFAULT_ACL = None
 # https://django-storages.readthedocs.io/en/latest/backends/amazon-S3.html#settings
 AWS_S3_REGION_NAME = env("DJANGO_AWS_S3_REGION_NAME", default=None)
+{% elif cookiecutter.cloud_provider == 'GCE' %}
+DEFAULT_FILE_STORAGE = "storages.backends.gcloud.GoogleCloudStorage"
+GS_BUCKET_NAME = env("DJANGO_GCE_STORAGE_BUCKET_NAME")
+GS_DEFAULT_ACL = "publicRead"
+{% endif %}
 
 # STATIC
 # ------------------------
 {% if cookiecutter.use_whitenoise == 'y' -%}
 STATICFILES_STORAGE = "whitenoise.storage.CompressedManifestStaticFilesStorage"
-{%- else %}
+{%- endif -%}
+{%- if cookiecutter.cloud_provider == 'AWS' %}
 STATICFILES_STORAGE = "config.settings.production.StaticRootS3Boto3Storage"
 STATIC_URL = f"https://{AWS_STORAGE_BUCKET_NAME}.s3.amazonaws.com/static/"
+{%- elif cookiecutter.cloud_provider == 'GCE' %}
+STATIC_URL = "https://storage.googleapis.com/{}/static".format(GS_BUCKET_NAME)
 {%- endif %}
 
 # MEDIA
 # ------------------------------------------------------------------------------
-{% if cookiecutter.use_whitenoise == 'y' -%}
-DEFAULT_FILE_STORAGE = "storages.backends.s3boto3.S3Boto3Storage"
-MEDIA_URL = f"https://{AWS_STORAGE_BUCKET_NAME}.s3.amazonaws.com/"
-{%- else %}
+{%- if cookiecutter.cloud_provider == 'AWS' %}
 # region http://stackoverflow.com/questions/10390244/
 # Full-fledge class: https://stackoverflow.com/a/18046120/104731
 from storages.backends.s3boto3 import S3Boto3Storage  # noqa E402
@@ -121,6 +127,9 @@ class MediaRootS3Boto3Storage(S3Boto3Storage):
 # endregion
 DEFAULT_FILE_STORAGE = "config.settings.production.MediaRootS3Boto3Storage"
 MEDIA_URL = f"https://{AWS_STORAGE_BUCKET_NAME}.s3.amazonaws.com/media/"
+{%- elif cookiecutter.cloud_provider == 'GCE' %}
+MEDIA_URL = "https://storage.googleapis.com/{}/media".format(GS_BUCKET_NAME)
+MEDIA_ROOT = "https://storage.googleapis.com/{}/media".format(GS_BUCKET_NAME)
 {%- endif %}
 
 # TEMPLATES


Test patch:
diff --git a/tests/test_cookiecutter_generation.py b/tests/test_cookiecutter_generation.py
--- a/tests/test_cookiecutter_generation.py
+++ b/tests/test_cookiecutter_generation.py
@@ -11,6 +11,7 @@
 RE_OBJ = re.compile(PATTERN)
 
 YN_CHOICES = ["y", "n"]
+CLOUD_CHOICES = ["AWS", "GCE"]
 
 
 @pytest.fixture
@@ -35,6 +36,7 @@ def context():
 @pytest.mark.parametrize("use_sentry", YN_CHOICES, ids=lambda yn: f"sentry:{yn}")
 @pytest.mark.parametrize("use_compressor", YN_CHOICES, ids=lambda yn: f"cmpr:{yn}")
 @pytest.mark.parametrize("use_whitenoise", YN_CHOICES, ids=lambda yn: f"wnoise:{yn}")
+@pytest.mark.parametrize("cloud_provider", CLOUD_CHOICES, ids=lambda yn: f"cloud:{yn}")
 def context_combination(
     windows,
     use_docker,
@@ -43,6 +45,7 @@ def context_combination(
     use_sentry,
     use_compressor,
     use_whitenoise,
+    cloud_provider,
 ):
     """Fixture that parametrize the function where it's used."""
     return {
@@ -53,6 +56,7 @@ def context_combination(
         "use_mailhog": use_mailhog,
         "use_sentry": use_sentry,
         "use_whitenoise": use_whitenoise,
+        "cloud_provider": cloud_provider,
     }