diff options
| author | Yuval Adam <yuval@segmanta.com> | 2014-03-20 17:49:16 +0200 |
|---|---|---|
| committer | Yuval Adam <yuval@segmanta.com> | 2014-03-20 17:49:16 +0200 |
| commit | 75f93a3f7854a7383febd047391e2bfd4caceee0 (patch) | |
| tree | d5e634ef292c6b84acacc3982dbcaa0d300a346e /storages/backends/mogile.py | |
Diffstat (limited to 'storages/backends/mogile.py')
| -rw-r--r-- | storages/backends/mogile.py | 118 |
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 |
