forked from CGM_Public/pretix_original
Refs #44 -- Added background queue support for file export
This commit is contained in:
@@ -8,6 +8,7 @@ class PretixBaseConfig(AppConfig):
|
||||
def ready(self):
|
||||
from . import exporter # NOQA
|
||||
from . import payment # NOQA
|
||||
from .services import export, mail # NOQA
|
||||
|
||||
try:
|
||||
from .celery import app as celery_app # NOQA
|
||||
|
||||
@@ -1,3 +1,7 @@
|
||||
import decimal
|
||||
import json
|
||||
|
||||
from django.core.serializers.json import DjangoJSONEncoder
|
||||
from django.dispatch import receiver
|
||||
from django.http import HttpRequest, HttpResponse, JsonResponse
|
||||
|
||||
@@ -58,13 +62,13 @@ class BaseExporter:
|
||||
"""
|
||||
return {}
|
||||
|
||||
def render(self, request: HttpRequest) -> HttpResponse:
|
||||
def render(self, form_data: dict) -> tuple:
|
||||
"""
|
||||
Render the exported file and return a request that either contains the file
|
||||
or redirects to it.
|
||||
Render the exported file and return a tuple consisting of a filename, a file type
|
||||
and file content.
|
||||
|
||||
:type request: HttpRequest
|
||||
:param request: The HTTP request of the user requesting the export
|
||||
:type form_data: dict
|
||||
:param form_data: The form data of the export details form
|
||||
"""
|
||||
raise NotImplementedError() # NOQA
|
||||
|
||||
@@ -73,7 +77,7 @@ class JSONExporter(BaseExporter):
|
||||
identifier = 'json'
|
||||
verbose_name = 'JSON'
|
||||
|
||||
def render(self, request):
|
||||
def render(self, form_data):
|
||||
jo = {
|
||||
'event': {
|
||||
'name': str(self.event.name),
|
||||
@@ -151,7 +155,7 @@ class JSONExporter(BaseExporter):
|
||||
}
|
||||
}
|
||||
|
||||
return JsonResponse(jo)
|
||||
return 'pretixdata.json', 'application/json', json.dumps(jo, cls=DjangoJSONEncoder)
|
||||
|
||||
|
||||
@receiver(register_data_exporters, dispatch_uid="exporter_json")
|
||||
|
||||
59
src/pretix/base/migrations/0009_auto_20150915_2003.py
Normal file
59
src/pretix/base/migrations/0009_auto_20150915_2003.py
Normal file
@@ -0,0 +1,59 @@
|
||||
# -*- coding: utf-8 -*-
|
||||
from __future__ import unicode_literals
|
||||
|
||||
import versions.models
|
||||
from django.db import migrations, models
|
||||
|
||||
import pretix.base.models
|
||||
|
||||
|
||||
class Migration(migrations.Migration):
|
||||
|
||||
dependencies = [
|
||||
('pretixbase', '0008_auto_20150804_1357'),
|
||||
]
|
||||
|
||||
operations = [
|
||||
migrations.CreateModel(
|
||||
name='CachedFile',
|
||||
fields=[
|
||||
('id', models.UUIDField(primary_key=True, serialize=False)),
|
||||
('expires', models.DateTimeField(null=True, blank=True)),
|
||||
('date', models.DateTimeField(null=True, blank=True)),
|
||||
('filename', models.CharField(max_length=255)),
|
||||
('file', models.FileField(null=True, upload_to=pretix.base.models.cachedfile_name, blank=True)),
|
||||
],
|
||||
),
|
||||
migrations.CreateModel(
|
||||
name='CachedTicket',
|
||||
fields=[
|
||||
('id', models.AutoField(primary_key=True, auto_created=True, verbose_name='ID', serialize=False)),
|
||||
('provider', models.CharField(max_length=255)),
|
||||
('cachedfile', models.ForeignKey(to='pretixbase.CachedFile')),
|
||||
('order', models.ForeignKey(to='pretixbase.Order')),
|
||||
],
|
||||
),
|
||||
migrations.AlterModelOptions(
|
||||
name='itemcategory',
|
||||
options={'verbose_name_plural': 'Product categories', 'ordering': ('position', 'version_birth_date'), 'verbose_name': 'Product category'},
|
||||
),
|
||||
migrations.AlterModelOptions(
|
||||
name='propertyvalue',
|
||||
options={'verbose_name_plural': 'Property values', 'ordering': ('position', 'version_birth_date'), 'verbose_name': 'Property value'},
|
||||
),
|
||||
migrations.AlterField(
|
||||
model_name='orderposition',
|
||||
name='item',
|
||||
field=versions.models.VersionedForeignKey(to='pretixbase.Item', verbose_name='Item', related_name='positions'),
|
||||
),
|
||||
migrations.AlterField(
|
||||
model_name='user',
|
||||
name='locale',
|
||||
field=models.CharField(choices=[('en', 'English'), ('de', 'German'), ('de-informal', 'German (informal)')], max_length=50, default='en', verbose_name='Language'),
|
||||
),
|
||||
migrations.AddField(
|
||||
model_name='order',
|
||||
name='tickets',
|
||||
field=models.ManyToManyField(to='pretixbase.CachedFile', through='pretixbase.CachedTicket'),
|
||||
),
|
||||
]
|
||||
20
src/pretix/base/migrations/0010_cachedfile_type.py
Normal file
20
src/pretix/base/migrations/0010_cachedfile_type.py
Normal file
@@ -0,0 +1,20 @@
|
||||
# -*- coding: utf-8 -*-
|
||||
from __future__ import unicode_literals
|
||||
|
||||
from django.db import migrations, models
|
||||
|
||||
|
||||
class Migration(migrations.Migration):
|
||||
|
||||
dependencies = [
|
||||
('pretixbase', '0009_auto_20150915_2003'),
|
||||
]
|
||||
|
||||
operations = [
|
||||
migrations.AddField(
|
||||
model_name='cachedfile',
|
||||
name='type',
|
||||
field=models.CharField(default='text/plain', max_length=255),
|
||||
preserve_default=False,
|
||||
),
|
||||
]
|
||||
21
src/pretix/base/migrations/0011_auto_20150915_2020.py
Normal file
21
src/pretix/base/migrations/0011_auto_20150915_2020.py
Normal file
@@ -0,0 +1,21 @@
|
||||
# -*- coding: utf-8 -*-
|
||||
from __future__ import unicode_literals
|
||||
|
||||
import uuid
|
||||
|
||||
from django.db import migrations, models
|
||||
|
||||
|
||||
class Migration(migrations.Migration):
|
||||
|
||||
dependencies = [
|
||||
('pretixbase', '0010_cachedfile_type'),
|
||||
]
|
||||
|
||||
operations = [
|
||||
migrations.AlterField(
|
||||
model_name='cachedfile',
|
||||
name='id',
|
||||
field=models.UUIDField(serialize=False, primary_key=True, default=uuid.uuid4),
|
||||
),
|
||||
]
|
||||
18
src/pretix/base/migrations/0012_remove_order_tickets.py
Normal file
18
src/pretix/base/migrations/0012_remove_order_tickets.py
Normal file
@@ -0,0 +1,18 @@
|
||||
# -*- coding: utf-8 -*-
|
||||
from __future__ import unicode_literals
|
||||
|
||||
from django.db import migrations, models
|
||||
|
||||
|
||||
class Migration(migrations.Migration):
|
||||
|
||||
dependencies = [
|
||||
('pretixbase', '0011_auto_20150915_2020'),
|
||||
]
|
||||
|
||||
operations = [
|
||||
migrations.RemoveField(
|
||||
model_name='order',
|
||||
name='tickets',
|
||||
),
|
||||
]
|
||||
@@ -291,6 +291,22 @@ class User(AbstractBaseUser, PermissionsMixin):
|
||||
return self.identifier # NOQA
|
||||
|
||||
|
||||
def cachedfile_name(instance, filename):
|
||||
return 'cachedfiles/%s.%s' % (instance.id, filename.split('.')[-1])
|
||||
|
||||
|
||||
class CachedFile(models.Model):
|
||||
"""
|
||||
A cached file (e.g. pre-generated ticket PDF)
|
||||
"""
|
||||
id = models.UUIDField(primary_key=True, default=uuid.uuid4)
|
||||
expires = models.DateTimeField(null=True, blank=True)
|
||||
date = models.DateTimeField(null=True, blank=True)
|
||||
filename = models.CharField(max_length=255)
|
||||
type = models.CharField(max_length=255)
|
||||
file = models.FileField(null=True, blank=True, upload_to=cachedfile_name)
|
||||
|
||||
|
||||
class Organizer(Versionable):
|
||||
"""
|
||||
This model represents an entity organizing events, e.g. a company, institution,
|
||||
@@ -1687,6 +1703,12 @@ class Order(Versionable):
|
||||
return True, quotas_locked
|
||||
|
||||
|
||||
class CachedTicket(models.Model):
|
||||
order = models.ForeignKey(Order, on_delete=models.CASCADE)
|
||||
cachedfile = models.ForeignKey(CachedFile, on_delete=models.CASCADE)
|
||||
provider = models.CharField(max_length=255)
|
||||
|
||||
|
||||
class QuestionAnswer(Versionable):
|
||||
"""
|
||||
The answer to a Question, connected to an OrderPosition or CartPosition.
|
||||
|
||||
23
src/pretix/base/services/export.py
Normal file
23
src/pretix/base/services/export.py
Normal file
@@ -0,0 +1,23 @@
|
||||
from django.conf import settings
|
||||
from django.core.files.base import ContentFile
|
||||
|
||||
from pretix.base.models import CachedFile, Event, cachedfile_name
|
||||
from pretix.base.signals import register_data_exporters
|
||||
|
||||
|
||||
def export(event, fileid, provider, form_data):
|
||||
event = Event.objects.current.get(identity=event)
|
||||
file = CachedFile.objects.get(id=fileid)
|
||||
responses = register_data_exporters.send(event)
|
||||
for receiver, response in responses:
|
||||
ex = response(event)
|
||||
if ex.identifier == provider:
|
||||
file.filename, file.type, data = ex.render(form_data)
|
||||
file.file.save(cachedfile_name(file, file.filename), ContentFile(data))
|
||||
|
||||
|
||||
if settings.HAS_CELERY:
|
||||
from pretix.celery import app
|
||||
|
||||
export_task = app.task(export)
|
||||
export = lambda *args, **kwargs: export_task.apply_async(args=args, kwargs=kwargs)
|
||||
@@ -82,7 +82,7 @@ def mail_send(to, subject, body, sender):
|
||||
return False
|
||||
|
||||
|
||||
if settings.HAS_CELERY:
|
||||
if settings.HAS_CELERY and settings.EMAIL_BACKEND != 'django.core.mail.outbox':
|
||||
from pretix.celery import app
|
||||
|
||||
mail_send_task = app.task(mail_send)
|
||||
|
||||
Reference in New Issue
Block a user