forked from CGM_Public/pretix_original
Sendmail: Keep uploaded attachment when preview is used
This commit is contained in:
@@ -4,3 +4,4 @@
|
|||||||
<label for="{{ widget.checkbox_id }}">{{ widget.clear_checkbox_label }}</label>{% endif %}{% if widget.value.is_img %}<br><a href="{{ widget.value.url }}" data-lightbox="{{ widget.value.name }}"><img src="{{ widget.value|thumb:"200x100" }}" /></a>{% endif %}<br>
|
<label for="{{ widget.checkbox_id }}">{{ widget.clear_checkbox_label }}</label>{% endif %}{% if widget.value.is_img %}<br><a href="{{ widget.value.url }}" data-lightbox="{{ widget.value.name }}"><img src="{{ widget.value|thumb:"200x100" }}" /></a>{% endif %}<br>
|
||||||
{{ widget.input_text }}:{% endif %}
|
{{ widget.input_text }}:{% endif %}
|
||||||
<input type="{{ widget.type }}" name="{{ widget.name }}"{% include "django/forms/widgets/attrs.html" %}>
|
<input type="{{ widget.type }}" name="{{ widget.name }}"{% include "django/forms/widgets/attrs.html" %}>
|
||||||
|
{% if widget.cachedfile %}<input type="hidden" name="{{ widget.hidden_name }}" value="{{ widget.cachedfile.id }}">{% endif %}
|
||||||
|
|||||||
@@ -7,6 +7,7 @@ from django.core.exceptions import ValidationError
|
|||||||
from django.core.files import File
|
from django.core.files import File
|
||||||
from django.core.files.uploadedfile import UploadedFile
|
from django.core.files.uploadedfile import UploadedFile
|
||||||
from django.forms.utils import from_current_timezone
|
from django.forms.utils import from_current_timezone
|
||||||
|
from django.utils.timezone import now
|
||||||
from django.utils.translation import gettext_lazy as _
|
from django.utils.translation import gettext_lazy as _
|
||||||
|
|
||||||
from ...base.forms import I18nModelForm
|
from ...base.forms import I18nModelForm
|
||||||
@@ -77,6 +78,8 @@ class ClearableBasenameFileInput(forms.ClearableFileInput):
|
|||||||
|
|
||||||
@property
|
@property
|
||||||
def name(self):
|
def name(self):
|
||||||
|
if hasattr(self.file, 'display_name'):
|
||||||
|
return self.file.display_name
|
||||||
return self.file.name
|
return self.file.name
|
||||||
|
|
||||||
@property
|
@property
|
||||||
@@ -84,6 +87,8 @@ class ClearableBasenameFileInput(forms.ClearableFileInput):
|
|||||||
return any(self.file.name.lower().endswith(e) for e in ('.jpg', '.jpeg', '.png', '.gif'))
|
return any(self.file.name.lower().endswith(e) for e in ('.jpg', '.jpeg', '.png', '.gif'))
|
||||||
|
|
||||||
def __str__(self):
|
def __str__(self):
|
||||||
|
if hasattr(self.file, 'display_name'):
|
||||||
|
return self.file.display_name
|
||||||
return os.path.basename(self.file.name).split('.', 1)[-1]
|
return os.path.basename(self.file.name).split('.', 1)[-1]
|
||||||
|
|
||||||
@property
|
@property
|
||||||
@@ -93,6 +98,48 @@ class ClearableBasenameFileInput(forms.ClearableFileInput):
|
|||||||
def get_context(self, name, value, attrs):
|
def get_context(self, name, value, attrs):
|
||||||
ctx = super().get_context(name, value, attrs)
|
ctx = super().get_context(name, value, attrs)
|
||||||
ctx['widget']['value'] = self.FakeFile(value)
|
ctx['widget']['value'] = self.FakeFile(value)
|
||||||
|
ctx['widget']['cachedfile'] = None
|
||||||
|
return ctx
|
||||||
|
|
||||||
|
|
||||||
|
class CachedFileInput(forms.ClearableFileInput):
|
||||||
|
template_name = 'pretixbase/forms/widgets/thumbnailed_file_input.html'
|
||||||
|
|
||||||
|
class FakeFile(File):
|
||||||
|
def __init__(self, file):
|
||||||
|
self.file = file
|
||||||
|
|
||||||
|
@property
|
||||||
|
def name(self):
|
||||||
|
return self.file.filename
|
||||||
|
|
||||||
|
@property
|
||||||
|
def is_img(self):
|
||||||
|
return any(self.file.filename.lower().endswith(e) for e in ('.jpg', '.jpeg', '.png', '.gif'))
|
||||||
|
|
||||||
|
def __str__(self):
|
||||||
|
return self.file.filename
|
||||||
|
|
||||||
|
@property
|
||||||
|
def url(self):
|
||||||
|
return self.file.file.url
|
||||||
|
|
||||||
|
def value_from_datadict(self, data, files, name):
|
||||||
|
from ...base.models import CachedFile
|
||||||
|
v = super().value_from_datadict(data, files, name)
|
||||||
|
if v is None and data.get(name + '-cachedfile'): # An explicit "[x] clear" would be False, not None
|
||||||
|
return CachedFile.objects.filter(id=data[name + '-cachedfile']).first()
|
||||||
|
return v
|
||||||
|
|
||||||
|
def get_context(self, name, value, attrs):
|
||||||
|
from ...base.models import CachedFile
|
||||||
|
if isinstance(value, CachedFile):
|
||||||
|
value = self.FakeFile(value)
|
||||||
|
|
||||||
|
ctx = super().get_context(name, value, attrs)
|
||||||
|
ctx['widget']['value'] = value
|
||||||
|
ctx['widget']['cachedfile'] = value.file if isinstance(value, self.FakeFile) else None
|
||||||
|
ctx['widget']['hidden_name'] = name + '-cachedfile'
|
||||||
return ctx
|
return ctx
|
||||||
|
|
||||||
|
|
||||||
@@ -129,7 +176,7 @@ class ExtFileField(SizeFileField):
|
|||||||
|
|
||||||
def clean(self, *args, **kwargs):
|
def clean(self, *args, **kwargs):
|
||||||
data = super().clean(*args, **kwargs)
|
data = super().clean(*args, **kwargs)
|
||||||
if data:
|
if isinstance(data, File):
|
||||||
filename = data.name
|
filename = data.name
|
||||||
ext = os.path.splitext(filename)[1]
|
ext = os.path.splitext(filename)[1]
|
||||||
ext = ext.lower()
|
ext = ext.lower()
|
||||||
@@ -138,6 +185,49 @@ class ExtFileField(SizeFileField):
|
|||||||
return data
|
return data
|
||||||
|
|
||||||
|
|
||||||
|
class CachedFileField(ExtFileField):
|
||||||
|
widget = CachedFileInput
|
||||||
|
|
||||||
|
def to_python(self, data):
|
||||||
|
from ...base.models import CachedFile
|
||||||
|
|
||||||
|
if isinstance(data, CachedFile):
|
||||||
|
return data
|
||||||
|
|
||||||
|
return super().to_python(data)
|
||||||
|
|
||||||
|
def bound_data(self, data, initial):
|
||||||
|
from ...base.models import CachedFile
|
||||||
|
|
||||||
|
if isinstance(data, File):
|
||||||
|
cf = CachedFile.objects.create(
|
||||||
|
expires=now() + datetime.timedelta(days=1),
|
||||||
|
date=now(),
|
||||||
|
filename=data.name,
|
||||||
|
type=data.content_type,
|
||||||
|
)
|
||||||
|
cf.file.save(data.name, data.file)
|
||||||
|
cf.save()
|
||||||
|
return cf
|
||||||
|
return super().bound_data(data, initial)
|
||||||
|
|
||||||
|
def clean(self, *args, **kwargs):
|
||||||
|
from ...base.models import CachedFile
|
||||||
|
|
||||||
|
data = super().clean(*args, **kwargs)
|
||||||
|
if isinstance(data, File):
|
||||||
|
cf = CachedFile.objects.create(
|
||||||
|
expires=now() + datetime.timedelta(days=1),
|
||||||
|
date=now(),
|
||||||
|
filename=data.name,
|
||||||
|
type=data.content_type,
|
||||||
|
)
|
||||||
|
cf.file.save(data.name, data.file)
|
||||||
|
cf.save()
|
||||||
|
return cf
|
||||||
|
return data
|
||||||
|
|
||||||
|
|
||||||
class SlugWidget(forms.TextInput):
|
class SlugWidget(forms.TextInput):
|
||||||
template_name = 'pretixcontrol/slug_widget.html'
|
template_name = 'pretixcontrol/slug_widget.html'
|
||||||
prefix = ''
|
prefix = ''
|
||||||
|
|||||||
@@ -9,7 +9,7 @@ from pretix.base.email import get_available_placeholders
|
|||||||
from pretix.base.forms import PlaceholderValidator
|
from pretix.base.forms import PlaceholderValidator
|
||||||
from pretix.base.forms.widgets import SplitDateTimePickerWidget
|
from pretix.base.forms.widgets import SplitDateTimePickerWidget
|
||||||
from pretix.base.models import CheckinList, Item, Order, SubEvent
|
from pretix.base.models import CheckinList, Item, Order, SubEvent
|
||||||
from pretix.control.forms import ExtFileField
|
from pretix.control.forms import CachedFileField
|
||||||
from pretix.control.forms.widgets import Select2, Select2Multiple
|
from pretix.control.forms.widgets import Select2, Select2Multiple
|
||||||
|
|
||||||
|
|
||||||
@@ -23,7 +23,7 @@ class MailForm(forms.Form):
|
|||||||
sendto = forms.MultipleChoiceField() # overridden later
|
sendto = forms.MultipleChoiceField() # overridden later
|
||||||
subject = forms.CharField(label=_("Subject"))
|
subject = forms.CharField(label=_("Subject"))
|
||||||
message = forms.CharField(label=_("Message"))
|
message = forms.CharField(label=_("Message"))
|
||||||
attachment = ExtFileField(
|
attachment = CachedFileField(
|
||||||
label=_("Attachment"),
|
label=_("Attachment"),
|
||||||
required=False,
|
required=False,
|
||||||
ext_whitelist=(
|
ext_whitelist=(
|
||||||
|
|||||||
@@ -1,5 +1,4 @@
|
|||||||
import logging
|
import logging
|
||||||
from datetime import timedelta
|
|
||||||
|
|
||||||
import bleach
|
import bleach
|
||||||
import dateutil
|
import dateutil
|
||||||
@@ -13,7 +12,7 @@ from django.views.generic import FormView, ListView
|
|||||||
|
|
||||||
from pretix.base.email import get_available_placeholders
|
from pretix.base.email import get_available_placeholders
|
||||||
from pretix.base.i18n import LazyI18nString, language
|
from pretix.base.i18n import LazyI18nString, language
|
||||||
from pretix.base.models import CachedFile, LogEntry, Order, OrderPosition
|
from pretix.base.models import LogEntry, Order, OrderPosition
|
||||||
from pretix.base.models.event import SubEvent
|
from pretix.base.models.event import SubEvent
|
||||||
from pretix.base.services.mail import TolerantDict
|
from pretix.base.services.mail import TolerantDict
|
||||||
from pretix.base.templatetags.rich_text import markdown_compile_email
|
from pretix.base.templatetags.rich_text import markdown_compile_email
|
||||||
@@ -124,7 +123,6 @@ class SenderView(EventPermissionRequiredMixin, FormView):
|
|||||||
|
|
||||||
if self.request.POST.get("action") == "preview":
|
if self.request.POST.get("action") == "preview":
|
||||||
for l in self.request.event.settings.locales:
|
for l in self.request.event.settings.locales:
|
||||||
|
|
||||||
with language(l):
|
with language(l):
|
||||||
context_dict = TolerantDict()
|
context_dict = TolerantDict()
|
||||||
for k, v in get_available_placeholders(self.request.event, ['event', 'order',
|
for k, v in get_available_placeholders(self.request.event, ['event', 'order',
|
||||||
@@ -146,17 +144,6 @@ class SenderView(EventPermissionRequiredMixin, FormView):
|
|||||||
|
|
||||||
return self.get(self.request, *self.args, **self.kwargs)
|
return self.get(self.request, *self.args, **self.kwargs)
|
||||||
|
|
||||||
attachment = None
|
|
||||||
if 'attachment' in self.request.FILES:
|
|
||||||
attachment = self.request.FILES['attachment']
|
|
||||||
cf = CachedFile.objects.create(
|
|
||||||
expires=now() + timedelta(days=1),
|
|
||||||
date=now(),
|
|
||||||
filename=attachment.name,
|
|
||||||
type=attachment.content_type,
|
|
||||||
)
|
|
||||||
cf.file.save(attachment.name, attachment.file)
|
|
||||||
cf.save()
|
|
||||||
kwargs = {
|
kwargs = {
|
||||||
'recipients': form.cleaned_data['recipients'],
|
'recipients': form.cleaned_data['recipients'],
|
||||||
'event': self.request.event.pk,
|
'event': self.request.event.pk,
|
||||||
@@ -169,8 +156,8 @@ class SenderView(EventPermissionRequiredMixin, FormView):
|
|||||||
'checkin_lists': [i.pk for i in form.cleaned_data.get('checkin_lists')],
|
'checkin_lists': [i.pk for i in form.cleaned_data.get('checkin_lists')],
|
||||||
'filter_checkins': form.cleaned_data.get('filter_checkins'),
|
'filter_checkins': form.cleaned_data.get('filter_checkins'),
|
||||||
}
|
}
|
||||||
if attachment is not None:
|
if form.cleaned_data.get('attachment') is not None:
|
||||||
kwargs['attachments'] = [cf.id]
|
kwargs['attachments'] = [form.cleaned_data['attachment'].id]
|
||||||
|
|
||||||
send_mails.apply_async(
|
send_mails.apply_async(
|
||||||
kwargs=kwargs
|
kwargs=kwargs
|
||||||
|
|||||||
Reference in New Issue
Block a user