From 3fbad31ed17ac34ab8885e077dab546aeeea01e6 Mon Sep 17 00:00:00 2001 From: Denis Rykov Date: Tue, 15 Dec 2020 21:08:45 +0100 Subject: [PATCH] [azure] Add overrideable method to customize parameters on a per-key basis (#898) --- docs/backends/azure.rst | 5 ++++ storages/backends/azure_storage.py | 37 ++++++++++++++++++++++-------- 2 files changed, 33 insertions(+), 9 deletions(-) diff --git a/docs/backends/azure.rst b/docs/backends/azure.rst index 330cee16f..2c7b172dd 100644 --- a/docs/backends/azure.rst +++ b/docs/backends/azure.rst @@ -165,3 +165,8 @@ The following settings are available: A variable to set the Cache-Control HTTP response header. E.g. ``AZURE_CACHE_CONTROL = "public,max-age=31536000,immutable"`` + +``AZURE_OBJECT_PARAMETERS`` + + Use this to set content settings on all objects. To set these on a per-object + basis, subclass the backend and override ``AzureStorage.get_object_parameters``. diff --git a/storages/backends/azure_storage.py b/storages/backends/azure_storage.py index 206c3c3f7..d822b4612 100644 --- a/storages/backends/azure_storage.py +++ b/storages/backends/azure_storage.py @@ -129,6 +129,7 @@ def get_default_settings(self): return { "account_name": setting("AZURE_ACCOUNT_NAME"), "account_key": setting("AZURE_ACCOUNT_KEY"), + "object_parameters": setting("AZURE_OBJECT_PARAMETERS", {}), "azure_container": setting("AZURE_CONTAINER"), "azure_ssl": setting("AZURE_SSL", True), "upload_max_conn": setting("AZURE_UPLOAD_MAX_CONN", 2), @@ -242,11 +243,7 @@ def size(self, name): def _save(self, name, content): cleaned_name = clean_name(name) name = self._get_valid_path(name) - guessed_type, content_encoding = mimetypes.guess_type(name) - content_type = ( - _content_type(content) or - guessed_type or - self.default_content_type) + params = self._get_content_settings_parameters(name, content) # Unwrap django file (wrapped by parent's save call) if isinstance(content, File): @@ -257,10 +254,7 @@ def _save(self, name, content): container_name=self.azure_container, blob_name=name, stream=content, - content_settings=ContentSettings( - content_type=content_type, - content_encoding=content_encoding, - cache_control=self.cache_control), + content_settings=ContentSettings(**params), max_connections=self.upload_max_conn, timeout=self.timeout) return cleaned_name @@ -287,6 +281,31 @@ def url(self, name, expire=None): protocol=self.azure_protocol, **make_blob_url_kwargs) + def _get_content_settings_parameters(self, name, content=None): + params = {} + + guessed_type, content_encoding = mimetypes.guess_type(name) + content_type = ( + _content_type(content) or + guessed_type or + self.default_content_type) + + params['cache_control'] = self.cache_control + params['content_type'] = content_type + params['content_encoding'] = content_encoding + + params.update(self.get_object_parameters(name)) + return params + + def get_object_parameters(self, name): + """ + Returns a dictionary that is passed to content settings. Override this + method to adjust this on a per-object basis to set e.g ContentDisposition. + + By default, returns the value of AZURE_OBJECT_PARAMETERS. + """ + return self.object_parameters.copy() + def get_modified_time(self, name): """ Returns an (aware) datetime object containing the last modified time if