refactor some of the common image code into a PictureViewMixin, and make pictures work with the devserver
This commit is contained in:
parent
c532dac146
commit
b151192d02
|
@ -3,6 +3,8 @@ from django.shortcuts import redirect
|
||||||
from django.urls import reverse
|
from django.urls import reverse
|
||||||
from . import models
|
from . import models
|
||||||
from django.contrib import messages
|
from django.contrib import messages
|
||||||
|
import sys, mimetypes
|
||||||
|
from django.http import Http404, HttpResponse
|
||||||
|
|
||||||
|
|
||||||
class CreateProposalMixin(SingleObjectMixin):
|
class CreateProposalMixin(SingleObjectMixin):
|
||||||
|
@ -46,3 +48,42 @@ class EnsureUserOwnsProposalMixin(SingleObjectMixin):
|
||||||
# alright, continue with the request
|
# alright, continue with the request
|
||||||
return super().dispatch(request, *args, **kwargs)
|
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
|
||||||
|
|
||||||
|
|
||||||
|
|
|
@ -9,7 +9,7 @@ from django.contrib import messages
|
||||||
from django.shortcuts import redirect
|
from django.shortcuts import redirect
|
||||||
from django.urls import reverse
|
from django.urls import reverse
|
||||||
from camps.mixins import CampViewMixin
|
from camps.mixins import CampViewMixin
|
||||||
from .mixins import CreateProposalMixin, EnsureUnapprovedProposalMixin, EnsureUserOwnsProposalMixin, EnsureWritableCampMixin
|
from .mixins import CreateProposalMixin, EnsureUnapprovedProposalMixin, EnsureUserOwnsProposalMixin, EnsureWritableCampMixin, PictureViewMixin
|
||||||
from . import models
|
from . import models
|
||||||
import datetime, os
|
import datetime, os
|
||||||
|
|
||||||
|
@ -77,7 +77,7 @@ class SpeakerProposalDetailView(LoginRequiredMixin, CampViewMixin, EnsureUserOwn
|
||||||
|
|
||||||
|
|
||||||
@method_decorator(require_safe, name='dispatch')
|
@method_decorator(require_safe, name='dispatch')
|
||||||
class SpeakerProposalPictureView(LoginRequiredMixin, CampViewMixin, EnsureUserOwnsProposalMixin, DetailView):
|
class SpeakerProposalPictureView(LoginRequiredMixin, CampViewMixin, EnsureUserOwnsProposalMixin, PictureViewMixin, DetailView):
|
||||||
model = models.SpeakerProposal
|
model = models.SpeakerProposal
|
||||||
|
|
||||||
def get(self, request, *args, **kwargs):
|
def get(self, request, *args, **kwargs):
|
||||||
|
@ -85,31 +85,8 @@ class SpeakerProposalPictureView(LoginRequiredMixin, CampViewMixin, EnsureUserOw
|
||||||
if self.get_object().user != request.user:
|
if self.get_object().user != request.user:
|
||||||
raise Http404()
|
raise Http404()
|
||||||
|
|
||||||
# do we have the requested picture?
|
# get and return the response
|
||||||
if kwargs['picture'] == 'thumbnail':
|
response = self.get_picture_response()
|
||||||
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'] = ''
|
|
||||||
return response
|
return response
|
||||||
|
|
||||||
|
|
||||||
|
@ -163,38 +140,11 @@ class EventProposalDetailView(LoginRequiredMixin, CampViewMixin, EnsureUserOwnsP
|
||||||
|
|
||||||
|
|
||||||
@method_decorator(require_safe, name='dispatch')
|
@method_decorator(require_safe, name='dispatch')
|
||||||
class SpeakerPictureView(CampViewMixin, DetailView):
|
class SpeakerPictureView(CampViewMixin, PictureViewMixin, DetailView):
|
||||||
model = models.Speaker
|
model = models.Speaker
|
||||||
|
|
||||||
def get(self, request, *args, **kwargs):
|
def get(self, request, *args, **kwargs):
|
||||||
# is the speaker public, or owned by current user?
|
response = self.get_picture_response()
|
||||||
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'] = ''
|
|
||||||
return response
|
return response
|
||||||
|
|
||||||
|
|
||||||
|
|
Loading…
Reference in a new issue