summaryrefslogtreecommitdiff
path: root/storages/backends/mogile.py
diff options
context:
space:
mode:
Diffstat (limited to 'storages/backends/mogile.py')
-rw-r--r--storages/backends/mogile.py118
1 files changed, 118 insertions, 0 deletions
diff --git a/storages/backends/mogile.py b/storages/backends/mogile.py
new file mode 100644
index 0000000..e609ec7
--- /dev/null
+++ b/storages/backends/mogile.py
@@ -0,0 +1,118 @@
+from __future__ import print_function
+
+import urlparse
+import mimetypes
+from StringIO import StringIO
+
+from django.conf import settings
+from django.core.cache import cache
+from django.utils.text import force_unicode
+from django.core.files.storage import Storage
+from django.http import HttpResponse, HttpResponseNotFound
+from django.core.exceptions import ImproperlyConfigured
+
+try:
+ import mogilefs
+except ImportError:
+ raise ImproperlyConfigured("Could not load mogilefs dependency.\
+ \nSee http://mogilefs.pbworks.com/Client-Libraries")
+
+
+class MogileFSStorage(Storage):
+ """MogileFS filesystem storage"""
+ def __init__(self, base_url=settings.MEDIA_URL):
+
+ # the MOGILEFS_MEDIA_URL overrides MEDIA_URL
+ if hasattr(settings, 'MOGILEFS_MEDIA_URL'):
+ self.base_url = settings.MOGILEFS_MEDIA_URL
+ else:
+ self.base_url = base_url
+
+ for var in ('MOGILEFS_TRACKERS', 'MOGILEFS_DOMAIN',):
+ if not hasattr(settings, var):
+ raise ImproperlyConfigured("You must define %s to use the MogileFS backend." % var)
+
+ self.trackers = settings.MOGILEFS_TRACKERS
+ self.domain = settings.MOGILEFS_DOMAIN
+ self.client = mogilefs.Client(self.domain, self.trackers)
+
+ def get_mogile_paths(self, filename):
+ return self.client.get_paths(filename)
+
+ # The following methods define the Backend API
+
+ def filesize(self, filename):
+ raise NotImplemented
+ #return os.path.getsize(self._get_absolute_path(filename))
+
+ def path(self, filename):
+ paths = self.get_mogile_paths(filename)
+ if paths:
+ return self.get_mogile_paths(filename)[0]
+ else:
+ return None
+
+ def url(self, filename):
+ return urlparse.urljoin(self.base_url, filename).replace('\\', '/')
+
+ def open(self, filename, mode='rb'):
+ raise NotImplemented
+ #return open(self._get_absolute_path(filename), mode)
+
+ def exists(self, filename):
+ return filename in self.client
+
+ def save(self, filename, raw_contents):
+ filename = self.get_available_filename(filename)
+
+ if not hasattr(self, 'mogile_class'):
+ self.mogile_class = None
+
+ # Write the file to mogile
+ success = self.client.send_file(filename, StringIO(raw_contents), self.mogile_class)
+ if success:
+ print("Wrote file to key %s, %s@%s" % (filename, self.domain, self.trackers[0]))
+ else:
+ print("FAILURE writing file %s" % (filename))
+
+ return force_unicode(filename.replace('\\', '/'))
+
+ def delete(self, filename):
+
+ self.client.delete(filename)
+
+
+def serve_mogilefs_file(request, key=None):
+ """
+ Called when a user requests an image.
+ Either reproxy the path to perlbal, or serve the image outright
+ """
+ # not the best way to do this, since we create a client each time
+ mimetype = mimetypes.guess_type(key)[0] or "application/x-octet-stream"
+ client = mogilefs.Client(settings.MOGILEFS_DOMAIN, settings.MOGILEFS_TRACKERS)
+ if hasattr(settings, "SERVE_WITH_PERLBAL") and settings.SERVE_WITH_PERLBAL:
+ # we're reproxying with perlbal
+
+ # check the path cache
+
+ path = cache.get(key)
+
+ if not path:
+ path = client.get_paths(key)
+ cache.set(key, path, 60)
+
+ if path:
+ response = HttpResponse(content_type=mimetype)
+ response['X-REPROXY-URL'] = path[0]
+ else:
+ response = HttpResponseNotFound()
+
+ else:
+ # we don't have perlbal, let's just serve the image via django
+ file_data = client[key]
+ if file_data:
+ response = HttpResponse(file_data, mimetype=mimetype)
+ else:
+ response = HttpResponseNotFound()
+
+ return response