Use async actions for order export

This commit is contained in:
Raphael Michel
2017-04-11 12:12:40 +02:00
parent 7dd99f3d18
commit 07fed0acce
6 changed files with 80 additions and 18 deletions

View File

@@ -21,3 +21,4 @@ def export(event: str, fileid: str, provider: str, form_data: Dict[str, Any]) ->
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() file.save()
return file.pk

View File

@@ -72,6 +72,7 @@ class AsyncAction:
# but handle the mssage itself # but handle the mssage itself
data.update({ data.update({
'redirect': self.get_success_url(res.info), 'redirect': self.get_success_url(res.info),
'success': True,
'message': str(self.get_success_message(res.info)) 'message': str(self.get_success_message(res.info))
}) })
else: else:
@@ -80,6 +81,7 @@ class AsyncAction:
# but handle the mssage itself # but handle the mssage itself
data.update({ data.update({
'redirect': self.get_error_url(), 'redirect': self.get_error_url(),
'success': False,
'message': str(self.get_error_message(res.info)) 'message': str(self.get_error_message(res.info))
}) })
return data return data
@@ -103,6 +105,7 @@ class AsyncAction:
if "ajax" in self.request.POST or "ajax" in self.request.GET: if "ajax" in self.request.POST or "ajax" in self.request.GET:
return JsonResponse({ return JsonResponse({
'ready': True, 'ready': True,
'success': True,
'redirect': self.get_success_url(value), 'redirect': self.get_success_url(value),
'message': str(self.get_success_message(value)) 'message': str(self.get_success_message(value))
}) })
@@ -113,6 +116,7 @@ class AsyncAction:
if "ajax" in self.request.POST or "ajax" in self.request.GET: if "ajax" in self.request.POST or "ajax" in self.request.GET:
return JsonResponse({ return JsonResponse({
'ready': True, 'ready': True,
'success': False,
'redirect': self.get_error_url(), 'redirect': self.get_error_url(),
'message': str(self.get_error_message(exception)) 'message': str(self.get_error_message(exception))
}) })

View File

@@ -11,7 +11,9 @@
<h3 class="panel-title">{{ e.verbose_name }}</h3> <h3 class="panel-title">{{ e.verbose_name }}</h3>
</div> </div>
<div class="panel-body"> <div class="panel-body">
<form action="" method="post" class="form-horizontal"> <form action="{% url "control:event.orders.export.do" event=request.event.slug organizer=request.organizer.slug %}"
method="post" class="form-horizontal" data-asynctask data-asynctask-download
data-asynctask-long>
{% csrf_token %} {% csrf_token %}
<input type="hidden" name="exporter" value="{{ e.identifier }}" /> <input type="hidden" name="exporter" value="{{ e.identifier }}" />
{% bootstrap_form e.form layout='horizontal' %} {% bootstrap_form e.form layout='horizontal' %}

View File

@@ -122,6 +122,7 @@ urlpatterns = [
name='event.invoice.download'), name='event.invoice.download'),
url(r'^orders/overview/$', orders.OverView.as_view(), name='event.orders.overview'), url(r'^orders/overview/$', orders.OverView.as_view(), name='event.orders.overview'),
url(r'^orders/export/$', orders.ExportView.as_view(), name='event.orders.export'), url(r'^orders/export/$', orders.ExportView.as_view(), name='event.orders.export'),
url(r'^orders/export/do$', orders.ExportDoView.as_view(), name='event.orders.export.do'),
url(r'^orders/go$', orders.OrderGo.as_view(), name='event.orders.go'), url(r'^orders/go$', orders.OrderGo.as_view(), name='event.orders.go'),
url(r'^orders/$', orders.OrderList.as_view(), name='event.orders'), url(r'^orders/$', orders.OrderList.as_view(), name='event.orders'),
url(r'^waitinglist/$', waitinglist.WaitingListView.as_view(), name='event.orders.waitinglist'), url(r'^waitinglist/$', waitinglist.WaitingListView.as_view(), name='event.orders.waitinglist'),

View File

@@ -30,6 +30,7 @@ from pretix.base.services.stats import order_overview
from pretix.base.signals import ( from pretix.base.signals import (
register_data_exporters, register_payment_providers, register_data_exporters, register_payment_providers,
) )
from pretix.base.views.async import AsyncAction
from pretix.control.forms.orders import ( from pretix.control.forms.orders import (
CommentForm, ExporterForm, ExtendForm, OrderContactForm, OrderLocaleForm, CommentForm, ExporterForm, ExtendForm, OrderContactForm, OrderLocaleForm,
OrderPositionChangeForm, OrderPositionChangeForm,
@@ -622,9 +623,7 @@ class OrderGo(EventPermissionRequiredMixin, View):
return redirect('control:event.orders', event=request.event.slug, organizer=request.event.organizer.slug) return redirect('control:event.orders', event=request.event.slug, organizer=request.event.organizer.slug)
class ExportView(EventPermissionRequiredMixin, TemplateView): class ExportMixin:
permission = 'can_view_orders'
template_name = 'pretixcontrol/orders/export.html'
@cached_property @cached_property
def exporters(self): def exporters(self):
@@ -640,10 +639,22 @@ class ExportView(EventPermissionRequiredMixin, TemplateView):
exporters.append(ex) exporters.append(ex)
return exporters return exporters
def get_context_data(self, **kwargs):
ctx = super().get_context_data(**kwargs) class ExportDoView(EventPermissionRequiredMixin, ExportMixin, AsyncAction, View):
ctx['exporters'] = self.exporters permission = 'can_view_orders'
return ctx task = export
def get_success_message(self, value):
return None
def get_success_url(self, value):
return reverse('cachedfile.download', kwargs={'id': str(value)})
def get_error_url(self):
return reverse('control:event.orders.export', kwargs={
'event': self.request.event.slug,
'organizer': self.request.event.organizer.slug
})
@cached_property @cached_property
def exporter(self): def exporter(self):
@@ -651,13 +662,14 @@ class ExportView(EventPermissionRequiredMixin, TemplateView):
if ex.identifier == self.request.POST.get("exporter"): if ex.identifier == self.request.POST.get("exporter"):
return ex return ex
def post(self, *args, **kwargs): def post(self, request, *args, **kwargs):
if not self.exporter: if not self.exporter:
messages.error(self.request, _('The selected exporter was not found.')) messages.error(self.request, _('The selected exporter was not found.'))
return redirect('control:event.orders.export', kwargs={ return redirect('control:event.orders.export', kwargs={
'event': self.request.event.slug, 'event': self.request.event.slug,
'organizer': self.request.event.organizer.slug 'organizer': self.request.event.organizer.slug
}) })
if not self.exporter.form.is_valid(): if not self.exporter.form.is_valid():
messages.error(self.request, _('There was a problem processing your input. See below for error details.')) messages.error(self.request, _('There was a problem processing your input. See below for error details.'))
return self.get(*args, **kwargs) return self.get(*args, **kwargs)
@@ -666,6 +678,14 @@ class ExportView(EventPermissionRequiredMixin, TemplateView):
cf.date = now() cf.date = now()
cf.expires = now() + timedelta(days=3) cf.expires = now() + timedelta(days=3)
cf.save() cf.save()
export.apply_async(args=(self.request.event.id, str(cf.id), self.exporter.identifier, return self.do(self.request.event.id, str(cf.id), self.exporter.identifier, self.exporter.form.cleaned_data)
self.exporter.form.cleaned_data))
return redirect(reverse('cachedfile.download', kwargs={'id': str(cf.id)}))
class ExportView(EventPermissionRequiredMixin, ExportMixin, TemplateView):
permission = 'can_view_orders'
template_name = 'pretixcontrol/orders/export.html'
def get_context_data(self, **kwargs):
ctx = super().get_context_data(**kwargs)
ctx['exporters'] = self.exporters
return ctx

View File

@@ -2,6 +2,9 @@
var async_task_id = null; var async_task_id = null;
var async_task_timeout = null; var async_task_timeout = null;
var async_task_check_url = null; var async_task_check_url = null;
var async_task_old_url = null;
var async_task_is_download = false;
var async_task_is_long = false;
function async_task_check() { function async_task_check() {
"use strict"; "use strict";
@@ -20,13 +23,26 @@ function async_task_check() {
function async_task_check_callback(data, jqXHR, status) { function async_task_check_callback(data, jqXHR, status) {
"use strict"; "use strict";
if (data.ready && data.redirect) { if (data.ready && data.redirect) {
if (async_task_is_download && data.success) {
waitingDialog.hide();
if (location.href.indexOf("async_id") !== -1) {
history.replaceState({}, "pretix", async_task_old_url);
}
}
location.href = data.redirect; location.href = data.redirect;
return; return;
} }
async_task_timeout = window.setTimeout(async_task_check, 250); async_task_timeout = window.setTimeout(async_task_check, 250);
$("#loadingmodal p").text(gettext('Your request has been queued on the server and will now be ' +
'processed. If this takes longer than two minutes, please contact us or go ' + if (async_task_is_long) {
'back in your browser and try again.')); $("#loadingmodal p").text(gettext('Your request has been queued on the server and will now be ' +
'processed. Depending on the size of your event, this might take up to a ' +
'few minutes.'));
} else {
$("#loadingmodal p").text(gettext('Your request has been queued on the server and will now be ' +
'processed. If this takes longer than two minutes, please contact us or go ' +
'back in your browser and try again.'));
}
} }
function async_task_check_error(jqXHR, textStatus, errorThrown) { function async_task_check_error(jqXHR, textStatus, errorThrown) {
@@ -35,6 +51,9 @@ function async_task_check_error(jqXHR, textStatus, errorThrown) {
if (c.length > 0) { if (c.length > 0) {
$("body").data('ajaxing', false); $("body").data('ajaxing', false);
waitingDialog.hide(); waitingDialog.hide();
if (location.href.indexOf("async_id") !== -1) {
history.replaceState({}, "pretix", async_task_old_url);
}
ajaxErrDialog.show(c.first().html()); ajaxErrDialog.show(c.first().html());
} else { } else {
if (jqXHR.status >= 400 && jqXHR.status < 500) { if (jqXHR.status >= 400 && jqXHR.status < 500) {
@@ -54,6 +73,12 @@ function async_task_callback(data, jqXHR, status) {
"use strict"; "use strict";
$("body").data('ajaxing', false); $("body").data('ajaxing', false);
if (data.redirect) { if (data.redirect) {
if (async_task_is_download && data.success) {
waitingDialog.hide();
if (location.href.indexOf("async_id") !== -1) {
history.replaceState({}, "pretix", async_task_old_url);
}
}
location.href = data.redirect; location.href = data.redirect;
return; return;
} }
@@ -61,9 +86,15 @@ function async_task_callback(data, jqXHR, status) {
async_task_check_url = data.check_url; async_task_check_url = data.check_url;
async_task_timeout = window.setTimeout(async_task_check, 100); async_task_timeout = window.setTimeout(async_task_check, 100);
$("#loadingmodal p").text(gettext('Your request has been queued on the server and will now be ' + if (async_task_is_long) {
'processed. If this takes longer than two minutes, please contact us or go ' + $("#loadingmodal p").text(gettext('Your request has been queued on the server and will now be ' +
'back in your browser and try again.')); 'processed. Depending on the size of your event, this might take up to a ' +
'few minutes.'));
} else {
$("#loadingmodal p").text(gettext('Your request has been queued on the server and will now be ' +
'processed. If this takes longer than two minutes, please contact us or go ' +
'back in your browser and try again.'));
}
if (location.href.indexOf("async_id") === -1) { if (location.href.indexOf("async_id") === -1) {
history.pushState({}, "Waiting", async_task_check_url.replace(/ajax=1/, '')); history.pushState({}, "Waiting", async_task_check_url.replace(/ajax=1/, ''));
} }
@@ -99,6 +130,9 @@ $(function () {
return; return;
} }
async_task_id = null; async_task_id = null;
async_task_is_download = $(this).is("[data-asynctask-download]");
async_task_is_long = $(this).is("[data-asynctask-long]");
async_task_old_url = location.href;
$("body").data('ajaxing', true); $("body").data('ajaxing', true);
waitingDialog.show(gettext('We are processing your request …')); waitingDialog.show(gettext('We are processing your request …'));
$("#loadingmodal p").text(gettext('We are currently sending your request to the server. If this takes longer ' + $("#loadingmodal p").text(gettext('We are currently sending your request to the server. If this takes longer ' +