From 4d75c568b5303439f8168b242ac6ed60a14cd458 Mon Sep 17 00:00:00 2001 From: Raphael Michel Date: Mon, 16 Oct 2023 17:59:32 +0200 Subject: [PATCH] Support file upload in AsyncFormView and subevent editor --- src/pretix/base/views/tasks.py | 48 +++++++++++++++++-- .../pretixcontrol/subevents/bulk.html | 2 +- .../pretixcontrol/subevents/detail.html | 2 +- 3 files changed, 46 insertions(+), 6 deletions(-) diff --git a/src/pretix/base/views/tasks.py b/src/pretix/base/views/tasks.py index 4e4f28389..f7c78098a 100644 --- a/src/pretix/base/views/tasks.py +++ b/src/pretix/base/views/tasks.py @@ -20,6 +20,8 @@ # . # import logging +from collections import defaultdict +from datetime import timedelta from importlib import import_module from zoneinfo import ZoneInfo @@ -29,18 +31,20 @@ from celery.result import AsyncResult from django.conf import settings from django.contrib import messages from django.core.exceptions import PermissionDenied, ValidationError +from django.core.files.uploadedfile import UploadedFile from django.db import transaction from django.http import HttpResponse, JsonResponse, QueryDict from django.shortcuts import redirect, render from django.test import RequestFactory from django.utils import timezone, translation -from django.utils.timezone import get_current_timezone +from django.utils.datastructures import MultiValueDict +from django.utils.timezone import get_current_timezone, now from django.utils.translation import get_language, gettext as _ from django.views import View from django.views.generic import FormView from redis import ResponseError -from pretix.base.models import User +from pretix.base.models import CachedFile, User from pretix.base.services.tasks import ProfiledEventTask from pretix.celery_app import app @@ -228,15 +232,39 @@ class AsyncFormView(AsyncMixin, FormView): ) def __init_subclass__(cls): + class StoredUploadedFile(UploadedFile): + pass + def async_execute(self, *, request_path, query_string, form_kwargs, locale, tz, url_kwargs=None, url_args=None, organizer=None, event=None, user=None, session_key=None): view_instance = cls() form_kwargs['data'] = QueryDict(form_kwargs['data']) + + if form_kwargs['files']: + for k, l in form_kwargs['files'].items(): + uploadedfiles = [] + for cfid in l: + cf = CachedFile.objects.get(pk=cfid) + uploadedfiles.append(StoredUploadedFile( + file=cf.file, + name=cf.filename, + content_type=cf.type, + size=cf.file.size, + charset=None, + content_type_extra=None, + )) + + form_kwargs['files'][k] = uploadedfiles + form_kwargs['files'] = MultiValueDict(form_kwargs['files']) + req = RequestFactory().post( request_path + '?' + query_string, data=form_kwargs['data'].urlencode(), content_type='application/x-www-form-urlencoded' ) + if form_kwargs['files']: + req._load_post_and_files() + req._files = form_kwargs['files'] view_instance.request = req view_instance.kwargs = url_kwargs view_instance.args = url_args @@ -287,8 +315,19 @@ class AsyncFormView(AsyncMixin, FormView): return super().get(request, *args, **kwargs) def form_valid(self, form): - if form.files: - raise TypeError('File upload currently not supported in AsyncFormView') + files = defaultdict(list) + if self.request.FILES: + for k, v in self.request.FILES.items(): + cf = CachedFile.objects.create( + expires=now() + timedelta(hours=2), + date=now(), + web_download=False, + filename=v.name, + type=v.content_type, + ) + cf.file.save('uploaded_file.dat', v) + files[k].append(str(cf.pk)) + form_kwargs = { k: v for k, v in self.get_form_kwargs().items() } @@ -299,6 +338,7 @@ class AsyncFormView(AsyncMixin, FormView): form_kwargs['instance'] = None form_kwargs.setdefault('data', QueryDict()) form_kwargs['data'] = form_kwargs['data'].urlencode() + form_kwargs['files'] = files form_kwargs['initial'] = {} form_kwargs.pop('event', None) kwargs = { diff --git a/src/pretix/control/templates/pretixcontrol/subevents/bulk.html b/src/pretix/control/templates/pretixcontrol/subevents/bulk.html index 9430373c5..21f392f50 100644 --- a/src/pretix/control/templates/pretixcontrol/subevents/bulk.html +++ b/src/pretix/control/templates/pretixcontrol/subevents/bulk.html @@ -8,7 +8,7 @@ {% block title %}{% trans "Date" context "subevent" %}{% endblock %} {% block content %}

{% trans "Create multiple dates" context "subevent" %}

-
+ {% csrf_token %} {% bootstrap_form_errors form %} {% for f in itemvar_forms %} diff --git a/src/pretix/control/templates/pretixcontrol/subevents/detail.html b/src/pretix/control/templates/pretixcontrol/subevents/detail.html index cbef0f95c..ad1936c67 100644 --- a/src/pretix/control/templates/pretixcontrol/subevents/detail.html +++ b/src/pretix/control/templates/pretixcontrol/subevents/detail.html @@ -11,7 +11,7 @@ {% else %}

{% trans "Date" context "subevent" %}

{% endif %} - + {% csrf_token %} {% bootstrap_form_errors form %} {% for f in itemvar_forms %}