forked from CGM_Public/pretix_original
Refs #44 -- Added background queue support for ticket output
This commit is contained in:
@@ -8,7 +8,7 @@ class PretixBaseConfig(AppConfig):
|
|||||||
def ready(self):
|
def ready(self):
|
||||||
from . import exporter # NOQA
|
from . import exporter # NOQA
|
||||||
from . import payment # NOQA
|
from . import payment # NOQA
|
||||||
from .services import export, mail # NOQA
|
from .services import export, mail, tickets # NOQA
|
||||||
|
|
||||||
try:
|
try:
|
||||||
from .celery import app as celery_app # NOQA
|
from .celery import app as celery_app # NOQA
|
||||||
|
|||||||
@@ -14,6 +14,7 @@ def export(event, fileid, provider, form_data):
|
|||||||
if ex.identifier == provider:
|
if ex.identifier == provider:
|
||||||
file.filename, file.type, data = ex.render(form_data)
|
file.filename, file.type, data = ex.render(form_data)
|
||||||
file.file.save(cachedfile_name(file, file.filename), ContentFile(data))
|
file.file.save(cachedfile_name(file, file.filename), ContentFile(data))
|
||||||
|
file.save()
|
||||||
|
|
||||||
|
|
||||||
if settings.HAS_CELERY:
|
if settings.HAS_CELERY:
|
||||||
|
|||||||
34
src/pretix/base/services/tickets.py
Normal file
34
src/pretix/base/services/tickets.py
Normal file
@@ -0,0 +1,34 @@
|
|||||||
|
from datetime import timedelta
|
||||||
|
from django.conf import settings
|
||||||
|
from django.core.files.base import ContentFile
|
||||||
|
from django.utils.timezone import now
|
||||||
|
|
||||||
|
from pretix.base.models import CachedFile, cachedfile_name, Order, CachedTicket
|
||||||
|
from pretix.base.signals import register_ticket_outputs
|
||||||
|
|
||||||
|
|
||||||
|
def generate(order, provider):
|
||||||
|
order = Order.objects.current.select_related('event').get(identity=order)
|
||||||
|
ct = CachedTicket.objects.get_or_create(order=order, provider=provider)[0]
|
||||||
|
if not ct.cachedfile:
|
||||||
|
cf = CachedFile()
|
||||||
|
cf.date = now()
|
||||||
|
cf.expires = order.event.date_from + timedelta(days=30)
|
||||||
|
cf.save()
|
||||||
|
ct.cachedfile = cf
|
||||||
|
ct.save()
|
||||||
|
|
||||||
|
responses = register_ticket_outputs.send(order.event)
|
||||||
|
for receiver, response in responses:
|
||||||
|
prov = response(order.event)
|
||||||
|
if prov.identifier == provider:
|
||||||
|
ct.cachedfile.filename, ct.cachedfile.type, data = prov.generate(order)
|
||||||
|
ct.cachedfile.file.save(cachedfile_name(ct.cachedfile, ct.cachedfile.filename), ContentFile(data))
|
||||||
|
ct.cachedfile.save()
|
||||||
|
|
||||||
|
|
||||||
|
if settings.HAS_CELERY:
|
||||||
|
from pretix.celery import app
|
||||||
|
|
||||||
|
generate_task = app.task(generate)
|
||||||
|
generate = lambda *args, **kwargs: generate_task.apply_async(args=args, kwargs=kwargs)
|
||||||
@@ -28,9 +28,10 @@ class BaseTicketOutput:
|
|||||||
"""
|
"""
|
||||||
return self.settings.get('_enabled', as_type=bool)
|
return self.settings.get('_enabled', as_type=bool)
|
||||||
|
|
||||||
def generate(self, request: HttpRequest, order: Order) -> HttpResponse:
|
def generate(self, order: Order) -> tuple:
|
||||||
"""
|
"""
|
||||||
This method should generate the download file and return it to the user.
|
This method should generate the download file and return a tuple consisting of a
|
||||||
|
filename, a file type and file content.
|
||||||
"""
|
"""
|
||||||
raise NotImplementedError()
|
raise NotImplementedError()
|
||||||
|
|
||||||
|
|||||||
@@ -20,7 +20,7 @@ class PdfTicketOutput(BaseTicketOutput):
|
|||||||
download_button_text = _('Download PDF')
|
download_button_text = _('Download PDF')
|
||||||
download_button_icon = 'fa-print'
|
download_button_icon = 'fa-print'
|
||||||
|
|
||||||
def generate(self, request, order):
|
def generate(self, order):
|
||||||
from reportlab.graphics.shapes import Drawing
|
from reportlab.graphics.shapes import Drawing
|
||||||
from reportlab.pdfgen import canvas
|
from reportlab.pdfgen import canvas
|
||||||
from reportlab.lib import pagesizes, units
|
from reportlab.lib import pagesizes, units
|
||||||
@@ -28,9 +28,6 @@ class PdfTicketOutput(BaseTicketOutput):
|
|||||||
from reportlab.graphics import renderPDF
|
from reportlab.graphics import renderPDF
|
||||||
from PyPDF2 import PdfFileWriter, PdfFileReader
|
from PyPDF2 import PdfFileWriter, PdfFileReader
|
||||||
|
|
||||||
response = HttpResponse(content_type='application/pdf')
|
|
||||||
response['Content-Disposition'] = 'inline; filename="order%s%s.pdf"' % (request.event.slug, order.code)
|
|
||||||
|
|
||||||
pagesize = self.settings.get('pagesize', default='A4')
|
pagesize = self.settings.get('pagesize', default='A4')
|
||||||
if hasattr(pagesizes, pagesize):
|
if hasattr(pagesizes, pagesize):
|
||||||
pagesize = getattr(pagesizes, pagesize)
|
pagesize = getattr(pagesizes, pagesize)
|
||||||
@@ -55,7 +52,7 @@ class PdfTicketOutput(BaseTicketOutput):
|
|||||||
p.setFont("Helvetica", event_s)
|
p.setFont("Helvetica", event_s)
|
||||||
event_x = self.settings.get('event_x', default=15, as_type=float)
|
event_x = self.settings.get('event_x', default=15, as_type=float)
|
||||||
event_y = self.settings.get('event_y', default=235, as_type=float)
|
event_y = self.settings.get('event_y', default=235, as_type=float)
|
||||||
p.drawString(event_x * units.mm, event_y * units.mm, str(request.event.name))
|
p.drawString(event_x * units.mm, event_y * units.mm, str(self.event.name))
|
||||||
|
|
||||||
name_s = self.settings.get('name_s', default=17, as_type=float)
|
name_s = self.settings.get('name_s', default=17, as_type=float)
|
||||||
if name_s:
|
if name_s:
|
||||||
@@ -72,7 +69,7 @@ class PdfTicketOutput(BaseTicketOutput):
|
|||||||
p.setFont("Helvetica", price_s)
|
p.setFont("Helvetica", price_s)
|
||||||
price_x = self.settings.get('price_x', default=15, as_type=float)
|
price_x = self.settings.get('price_x', default=15, as_type=float)
|
||||||
price_y = self.settings.get('price_y', default=210, as_type=float)
|
price_y = self.settings.get('price_y', default=210, as_type=float)
|
||||||
p.drawString(price_x * units.mm, price_y * units.mm, "%s %s" % (str(op.price), request.event.currency))
|
p.drawString(price_x * units.mm, price_y * units.mm, "%s %s" % (str(op.price), self.event.currency))
|
||||||
|
|
||||||
qr_s = self.settings.get('qr_s', default=80, as_type=float)
|
qr_s = self.settings.get('qr_s', default=80, as_type=float)
|
||||||
if qr_s:
|
if qr_s:
|
||||||
@@ -107,8 +104,10 @@ class PdfTicketOutput(BaseTicketOutput):
|
|||||||
bg_page.mergePage(page)
|
bg_page.mergePage(page)
|
||||||
output.addPage(bg_page)
|
output.addPage(bg_page)
|
||||||
|
|
||||||
output.write(response)
|
outbuffer = BytesIO()
|
||||||
return response
|
output.write(outbuffer)
|
||||||
|
outbuffer.seek(0)
|
||||||
|
return 'order%s%s.pdf' % (self.event.slug, order.code), 'application/pdf', outbuffer.read()
|
||||||
|
|
||||||
@property
|
@property
|
||||||
def settings_form_fields(self) -> dict:
|
def settings_form_fields(self) -> dict:
|
||||||
|
|||||||
@@ -1,3 +1,4 @@
|
|||||||
|
from datetime import timedelta
|
||||||
from django.contrib import messages
|
from django.contrib import messages
|
||||||
from django.core.urlresolvers import reverse
|
from django.core.urlresolvers import reverse
|
||||||
from django.http import HttpResponseForbidden, HttpResponseNotFound
|
from django.http import HttpResponseForbidden, HttpResponseNotFound
|
||||||
@@ -7,7 +8,8 @@ from django.utils.timezone import now
|
|||||||
from django.utils.translation import ugettext_lazy as _
|
from django.utils.translation import ugettext_lazy as _
|
||||||
from django.views.generic import TemplateView, View
|
from django.views.generic import TemplateView, View
|
||||||
|
|
||||||
from pretix.base.models import Order, OrderPosition
|
from pretix.base.models import Order, OrderPosition, CachedTicket, CachedFile
|
||||||
|
from pretix.base.services.tickets import generate
|
||||||
from pretix.base.signals import (
|
from pretix.base.signals import (
|
||||||
register_payment_providers, register_ticket_outputs,
|
register_payment_providers, register_ticket_outputs,
|
||||||
)
|
)
|
||||||
@@ -277,4 +279,19 @@ class OrderDownload(EventViewMixin, EventLoginRequiredMixin, OrderDetailMixin,
|
|||||||
and now() < self.request.event.settings.ticket_download_date)):
|
and now() < self.request.event.settings.ticket_download_date)):
|
||||||
messages.error(request, _('Ticket download is not (yet) enabled.'))
|
messages.error(request, _('Ticket download is not (yet) enabled.'))
|
||||||
return redirect(self.get_order_url())
|
return redirect(self.get_order_url())
|
||||||
return self.output.generate(request, self.order)
|
|
||||||
|
try:
|
||||||
|
ct = CachedTicket.objects.get(order=self.order, provider=self.output.identifier)
|
||||||
|
except CachedTicket.DoesNotExist:
|
||||||
|
ct = CachedTicket(order=self.order, provider=self.output.identifier)
|
||||||
|
try:
|
||||||
|
ct.cachedfile
|
||||||
|
except CachedFile.DoesNotExist:
|
||||||
|
cf = CachedFile()
|
||||||
|
cf.date = now()
|
||||||
|
cf.expires = self.request.event.date_from + timedelta(days=30)
|
||||||
|
cf.save()
|
||||||
|
ct.cachedfile = cf
|
||||||
|
ct.save()
|
||||||
|
generate(self.order.identity, self.output.identifier)
|
||||||
|
return redirect(reverse('presale:cachedfile.download', kwargs={'id': ct.cachedfile.id}))
|
||||||
|
|||||||
Reference in New Issue
Block a user