1. David Bennett
  2. django-private-media

Commits

David Bennett  committed b23045a

Added nginx handler.

  • Participants
  • Parent commits 07d03c9
  • Branches default

Comments (0)

Files changed (5)

File docs/settings.rst

View file
  • Ignore whitespace
 
 .. attribute:: PRIVATE_MEDIA_URL
 
-    :default: ``'/_private/'``
+    :default: ``'/_private/media/'``
 
     The URL prefix for Nginx internal location.
 
     :default: ``True``
 
     Whether or not to base64 encode part of the URL.
+
+.. attribute:: PRIVATE_MEDIA_INSECURE
+
+    :default: ``django.conf.settings.DEBUG``
+
+    Whether or not to serve files directly from Django.
+
+.. attribute:: PRIVATE_MEDIA_DEFAULT_HANDLER
+
+    :default: ``private_media.handlers.nginx``
+
+    Default handler to use when not serving directly from Django.

File private_media/conf.py

View file
  • Ignore whitespace
 
 class PrivateMediaConf(AppConf):
     # The URL prefix for Nginx internal location
-    URL = '/_private/'
+    URL = '/_private/media/'
     # Whether or not to base64 encode part of the URL
     ENCODE_URL = True
+    # Whether or not to serve files directly from Django
+    INSECURE = None
+    # Default handler to use when not serving directly from Django
+    DEFAULT_HANDLER = 'private_media.handlers.nginx'
 
     class Meta:
         prefix = 'private_media'
+
+    def configure_insecure(self, value):
+        return settings.DEBUG if value is None else value

File private_media/fields.py

View file
  • Ignore whitespace
         return self.field.disposition
     disposition = property(_get_disposition)
 
+    def _get_handler(self):
+        return self.field.handler
+    handler = property(_get_handler)
+
     def _get_url(self):
         self._require_file()
         content_type = ContentType.objects.get_for_model(self.instance)
     attr_class = PrivateFieldFile
 
     def __init__(self, verbose_name=None, name=None, upload_to='',
-                 storage=None, condition=None, disposition=None, **kwargs):
+                 storage=None, condition=None, disposition=None, handler=None,
+                 **kwargs):
         self.condition = condition or user_is_authenticated
         self.disposition = disposition
+        self.handler = handler or settings.PRIVATE_MEDIA_DEFAULT_HANDLER
         super(PrivateFileField, self).__init__(
             verbose_name=verbose_name, name=name, upload_to=upload_to,
             storage=storage, **kwargs)
 
     def __init__(self, verbose_name=None, name=None, width_field=None,
                  height_field=None, condition=None, disposition=None,
-                 **kwargs):
+                 handler=None, **kwargs):
         self.condition = condition or user_is_authenticated
         self.disposition = disposition
+        self.handler = handler or settings.PRIVATE_MEDIA_DEFAULT_HANDLER
         super(PrivateImageField, self).__init__(
             verbose_name=verbose_name, name=name, width_field=width_field,
             height_field=height_field, **kwargs)

File private_media/handlers.py

View file
  • Ignore whitespace
+from urlparse import urljoin
+from django.conf import settings
+from django.http import HttpResponse
+
+
+def nginx(request, file):
+    response = HttpResponse()
+    response['Content-Type'] = ''
+    response['X-Accel-Redirect'] = urljoin(
+        settings.PRIVATE_MEDIA_URL, file.name)
+    return response

File private_media/views.py

View file
  • Ignore whitespace
 from base64 import urlsafe_b64decode
 from django.contrib.contenttypes.models import ContentType
 from django.core.exceptions import PermissionDenied
+from django.core.urlresolvers import get_callable
 from django.http import Http404, HttpResponse
 from django.views.static import serve
 from private_media.conf import settings
             'pk': object_id,
             field_name: file_name,
         })
-    except Exception as e:
+    except Exception, e:
         raise Http404(e if settings.DEBUG else 'File not found.')
     file = getattr(instance, field_name)
     if not file.condition(request, instance):
         raise PermissionDenied
-    response = serve(request, file_name, document_root=settings.MEDIA_ROOT)
+    if settings.PRIVATE_MEDIA_INSECURE:
+        response = serve(request, file_name, document_root=settings.MEDIA_ROOT)
+    else:
+        handler = get_callable(file.handler, True)
+        if not callable(handler):
+            raise Http404("Error importing '%s'." % file.handler
+                          if settings.DEBUG else 'File not found.')
+        response = handler(request, file)
     if file.disposition is not None:
         response['Content-Disposition'] = '%s; filename="%s"' % (
             file.disposition, os.path.basename(file.name))