refactor some of the common image code into a PictureViewMixin, and make pictures work with the devserver

This commit is contained in:
Thomas Steen Rasmussen 2017-03-17 19:40:47 +01:00
parent c532dac146
commit b151192d02
2 changed files with 47 additions and 56 deletions

View file

@ -3,6 +3,8 @@ from django.shortcuts import redirect
from django.urls import reverse
from . import models
from django.contrib import messages
import sys, mimetypes
from django.http import Http404, HttpResponse
class CreateProposalMixin(SingleObjectMixin):
@ -46,3 +48,42 @@ class EnsureUserOwnsProposalMixin(SingleObjectMixin):
# alright, continue with the request
return super().dispatch(request, *args, **kwargs)
class PictureViewMixin(SingleObjectMixin):
def dispatch(self, request, *args, **kwargs):
# do we have the requested picture?
if kwargs['picture'] == 'thumbnail':
if self.get_object().picture_small:
self.picture = self.get_object().picture_small
else:
raise Http404()
elif kwargs['picture'] == 'large':
if self.get_object().picture_large:
self.picture = self.get_object().picture_large
else:
raise Http404()
else:
# only 'thumbnail' and 'large' pictures supported
raise Http404()
# alright, continue with the request
return super().dispatch(request, *args, **kwargs)
def get_picture_response(self):
if 'runserver' in sys.argv or 'runserver_plus' in sys.argv:
# this is a local devserver situation, guess mimetype from extension and return picture directly
response = HttpResponse(self.picture, content_type=mimetypes.types_map[".%s" % self.picture.name.split(".")[-1]])
else:
# make nginx serve the picture using X-Accel-Redirect
# (this works for nginx only, other webservers use x-sendfile)
# maybe make the header name configurable
response = HttpResponse()
response['X-Accel-Redirect'] = '/public/speakerproposals/%(campslug)s/%(proposaluuid)s/%(filename)s' % {
'campslug': self.camp.slug,
'proposaluuid': self.get_object().uuid,
'filename': os.path.basename(self.picture.name),
}
response['Content-Type'] = ''
return response

View file

@ -9,7 +9,7 @@ from django.contrib import messages
from django.shortcuts import redirect
from django.urls import reverse
from camps.mixins import CampViewMixin
from .mixins import CreateProposalMixin, EnsureUnapprovedProposalMixin, EnsureUserOwnsProposalMixin, EnsureWritableCampMixin
from .mixins import CreateProposalMixin, EnsureUnapprovedProposalMixin, EnsureUserOwnsProposalMixin, EnsureWritableCampMixin, PictureViewMixin
from . import models
import datetime, os
@ -77,7 +77,7 @@ class SpeakerProposalDetailView(LoginRequiredMixin, CampViewMixin, EnsureUserOwn
@method_decorator(require_safe, name='dispatch')
class SpeakerProposalPictureView(LoginRequiredMixin, CampViewMixin, EnsureUserOwnsProposalMixin, DetailView):
class SpeakerProposalPictureView(LoginRequiredMixin, CampViewMixin, EnsureUserOwnsProposalMixin, PictureViewMixin, DetailView):
model = models.SpeakerProposal
def get(self, request, *args, **kwargs):
@ -85,31 +85,8 @@ class SpeakerProposalPictureView(LoginRequiredMixin, CampViewMixin, EnsureUserOw
if self.get_object().user != request.user:
raise Http404()
# 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_large:
picture = self.get_object().picture_large
else:
raise Http404()
else:
# only 'thumbnail' and 'large' pictures supported
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'] = '/public/speakerproposals/%(campslug)s/%(proposaluuid)s/%(filename)s' % {
'campslug': self.camp.slug,
'proposaluuid': self.get_object().uuid,
'filename': os.path.basename(picture.name),
}
response['Content-Type'] = ''
# get and return the response
response = self.get_picture_response()
return response
@ -163,38 +140,11 @@ class EventProposalDetailView(LoginRequiredMixin, CampViewMixin, EnsureUserOwnsP
@method_decorator(require_safe, name='dispatch')
class SpeakerPictureView(CampViewMixin, DetailView):
class SpeakerPictureView(CampViewMixin, PictureViewMixin, DetailView):
model = models.Speaker
def get(self, request, *args, **kwargs):
# is the speaker public, or owned by current user?
if not self.get_object().is_public and self.get_object().user != request.user:
raise Http404()
# 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_large:
picture = self.get_object().picture_large
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'] = '/public/speakers/%(campslug)s/%(speakerslug)s/%(filename)s' % {
'campslug': self.camp.slug,
'speakerslug': self.get_object().slug,
'filename': os.path.basename(picture.name),
}
response['Content-Type'] = ''
response = self.get_picture_response()
return response