From 56d8a9765ddb6deadbee4534364f24a89c2ec34c Mon Sep 17 00:00:00 2001 From: Thomas Steen Rasmussen Date: Sun, 19 Feb 2017 13:15:55 +0100 Subject: [PATCH] add view to show speaker pictures without exposing all of MEDIA_ROOT --- src/bornhack/urls.py | 5 +++++ src/program/models.py | 8 ++++++-- src/program/views.py | 34 ++++++++++++++++++++++++++++++++++ 3 files changed, 45 insertions(+), 2 deletions(-) diff --git a/src/bornhack/urls.py b/src/bornhack/urls.py index 533ddecc..9b2fe88d 100644 --- a/src/bornhack/urls.py +++ b/src/bornhack/urls.py @@ -111,6 +111,11 @@ urlpatterns = [ SpeakerDetailView.as_view(), name='speaker_detail' ), + url( + r'^speakers/(?P[-_\w+]+)/pictures/(?P[-_\w+]+)/$', + SpeakerPictureView.as_view(), + name='speaker_picture', + ), url( r'^events/$', EventListView.as_view(), diff --git a/src/program/models.py b/src/program/models.py index f7338cec..6d9ffab6 100644 --- a/src/program/models.py +++ b/src/program/models.py @@ -103,8 +103,12 @@ class EventInstance(CreatedUpdatedModel): def get_speaker_picture_upload_path(instance, filename): - """ We want speaker pictures are saved as MEDIA_ROOT/speakers/bornhack-2016/filename """ - return 'speakers/%s/%s' % (instance.camp.slug, filename) + """ We want speaker pictures are saved as MEDIA_ROOT/speakers/camp-slug/speaker-slug/filename """ + return 'speakers/%(campslug)s/%(speakerslug)s/%(filename)s' % { + 'campslug': instance.camp.slug, + 'speakerslug': instance.slug, + 'filename': filename + } class Speaker(CreatedUpdatedModel): diff --git a/src/program/views.py b/src/program/views.py index 7aa49ae2..eb673de7 100644 --- a/src/program/views.py +++ b/src/program/views.py @@ -6,6 +6,40 @@ from . import models from django.http import Http404 import datetime from django.conf import settings +from django.views import View +from django.views.decorators.http import require_safe +from django.http import Http404 +from django.utils.decorators import method_decorator + +@method_decorator(require_safe, name='dispatch') +class SpeakerPictureView(CampViewMixin, DetailView): + model = models.Speaker + + def get(self, request, *args, **kwargs): + # do we have the requested picture? + if kwargs['picture'] == 'thumbnail': + if self.get_object().picture_small: + picture = self.get_object().picture_small + else: + raise Http404() + elif kwargs['picture'] == 'large': + if self.get_object().picture_small: + picture = self.get_object().picture_small + else: + raise Http404() + else: + raise Http404() + + # make nginx return the picture using X-Accel-Redirect + # (this works for nginx only, other webservers use x-sendfile), + # TODO: what about runserver mode here? + response = HttpResponse() + response['X-Accel-Redirect'] = '/_media/speakers/%(campslug)s/%(speakerslug)s/%(filename)s' % { + 'campslug': self.camp.slug, + 'speakerslug': self.get_object().slug, + 'filename': picture.name + } + return response class SpeakerDetailView(CampViewMixin, DetailView):