From 7b3ec3d414133520612af970e6d585c1ecbaa624 Mon Sep 17 00:00:00 2001 From: ppetrid Date: Mon, 5 Nov 2012 20:52:11 +0200 Subject: [PATCH 1/2] filename should not change when closing the fp --- django_dropbox/storage.py | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/django_dropbox/storage.py b/django_dropbox/storage.py index 7374fce..b4a151b 100644 --- a/django_dropbox/storage.py +++ b/django_dropbox/storage.py @@ -134,5 +134,6 @@ def write(self, content): def close(self): if self._is_dirty: - self._storage.client.put_file(self._name, self.file.getvalue()) + #saving the file should preserve the original filename + self._storage.client.put_file(self._name, self.file.getvalue(), True) self.file.close() \ No newline at end of file From 232e39f3807a9aa432a586ce2d5f25150ca727e2 Mon Sep 17 00:00:00 2001 From: ppetrid Date: Thu, 15 Nov 2012 00:59:44 +0200 Subject: [PATCH 2/2] add temporary cache for client metadata --- django_dropbox/settings.py | 2 ++ django_dropbox/storage.py | 41 +++++++++++++++++++++++++++++++++----- 2 files changed, 38 insertions(+), 5 deletions(-) diff --git a/django_dropbox/settings.py b/django_dropbox/settings.py index 5a5fd59..25b18ac 100644 --- a/django_dropbox/settings.py +++ b/django_dropbox/settings.py @@ -4,6 +4,8 @@ CONSUMER_SECRET = getattr(settings, 'DROPBOX_CONSUMER_SECRET', None) ACCESS_TOKEN = getattr(settings, 'DROPBOX_ACCESS_TOKEN', None) ACCESS_TOKEN_SECRET = getattr(settings, 'DROPBOX_ACCESS_TOKEN_SECRET', None) +#the seconds to cache metadata for a path to avoid unnecessary RESTful calls +DROPBOX_CACHE = getattr(settings, 'DROPBOX_CACHE', 10) # ACCESS_TYPE should be 'dropbox' or 'app_folder' as configured for your app ACCESS_TYPE = 'dropbox' diff --git a/django_dropbox/storage.py b/django_dropbox/storage.py index b4a151b..27a23f4 100644 --- a/django_dropbox/storage.py +++ b/django_dropbox/storage.py @@ -1,4 +1,5 @@ import errno +import md5 import os.path import re import urlparse @@ -11,13 +12,27 @@ from dropbox.session import DropboxSession from dropbox.client import DropboxClient from dropbox.rest import ErrorResponse +from django.core.cache import cache from django.core.files import File from django.core.files.storage import Storage from django.utils.encoding import filepath_to_uri from .settings import (CONSUMER_KEY, CONSUMER_SECRET, - ACCESS_TYPE, ACCESS_TOKEN, ACCESS_TOKEN_SECRET) + ACCESS_TYPE, ACCESS_TOKEN, ACCESS_TOKEN_SECRET, DROPBOX_CACHE) +def _cache_key(path): + """ + Return cache key for this path. + """ + return 'dropbox::storage::%s' % md5.new(path).hexdigest() + +def _clear_cache(path): + """ + Clear cache for this path. + """ + if DROPBOX_CACHE and isinstance(DROPBOX_CACHE, int): + cache.delete(_cache_key(path)) + class DropboxStorage(Storage): """ A storage class providing access to resources in a Dropbox Public folder. @@ -30,6 +45,19 @@ def __init__(self, location='/Public'): self.account_info = self.client.account_info() self.location = location self.base_url = 'http://dl.dropbox.com/u/{uid}/'.format(**self.account_info) + + def _client_metadata(self, path): + """ + Get client metadata from cache based on the DROPBOX_CACHE setting. + """ + if DROPBOX_CACHE and isinstance(DROPBOX_CACHE, int): + cache_key = _cache_key(path) + meta = cache.get(cache_key, None) + if not meta: + meta = self.client.metadata(path) + cache.set(cache_key, meta, DROPBOX_CACHE) + return meta + return self.client.metadata(path) def _get_abs_path(self, name): return os.path.realpath(os.path.join(self.location, name)) @@ -44,21 +72,23 @@ def _save(self, name, content): directory = os.path.dirname(name) if not self.exists(directory) and directory: self.client.file_create_folder(directory) - response = self.client.metadata(directory) + response = self._client_metadata(directory) if not response['is_dir']: raise IOError("%s exists and is not a directory." % directory) abs_name = os.path.realpath(os.path.join(self.location, name)) self.client.put_file(abs_name, content) + _clear_cache(abs_name) return name def delete(self, name): name = self._get_abs_path(name) self.client.file_delete(name) + _clear_cache(name) def exists(self, name): name = self._get_abs_path(name) try: - metadata = self.client.metadata(name) + metadata = self._client_metadata(name) if metadata.get('is_deleted'): return False except ErrorResponse as e: @@ -69,7 +99,7 @@ def exists(self, name): def listdir(self, path): path = self._get_abs_path(path) - response = self.client.metadata(path) + response = self._client_metadata(path) directories = [] files = [] for entry in response.get('contents', []): @@ -81,7 +111,7 @@ def listdir(self, path): def size(self, name): path = os.path.realpath(os.path.join(self.location, name)) - return self.client.metadata(path)['bytes'] + return self._client_metadata(path)['bytes'] def url(self, name): if name.startswith(self.location): @@ -136,4 +166,5 @@ def close(self): if self._is_dirty: #saving the file should preserve the original filename self._storage.client.put_file(self._name, self.file.getvalue(), True) + _clear_cache(self._name) self.file.close() \ No newline at end of file