Allowed settings to contain files

This commit is contained in:
Raphael Michel
2015-08-15 22:55:27 +02:00
parent 0ea6fe02d3
commit 30fd287aab
7 changed files with 85 additions and 12 deletions
+30
View File
@@ -1,6 +1,11 @@
import copy import copy
import logging
import os
from django import forms from django import forms
from django.conf import settings
from django.core.files import File
from django.core.files.uploadedfile import UploadedFile
from django.db import models from django.db import models
from django.forms.models import BaseModelForm, ModelFormMetaclass from django.forms.models import BaseModelForm, ModelFormMetaclass
from django.utils import six from django.utils import six
@@ -8,6 +13,9 @@ from django.utils.translation import ugettext_lazy as _
from versions.models import Versionable from versions.models import Versionable
from pretix.base.i18n import I18nFormField from pretix.base.i18n import I18nFormField
from pretix.base.models import Event
logger = logging.getLogger('pretix.plugins.ticketoutputpdf')
class BaseI18nModelForm(BaseModelForm): class BaseI18nModelForm(BaseModelForm):
@@ -89,6 +97,28 @@ class SettingsForm(forms.Form):
def save(self): def save(self):
for name, field in self.fields.items(): for name, field in self.fields.items():
value = self.cleaned_data[name] value = self.cleaned_data[name]
if isinstance(value, UploadedFile):
if isinstance(self.obj, Event):
fname = '%s/%s/%s.%s' % (
self.obj.organizer.slug, self.obj.slug, name, value.name.split('.')[-1]
)
else:
fname = '%s/%s.%s' % (self.obj.slug, name, value.name.split('.')[-1])
fpath = os.path.join(settings.MEDIA_ROOT, fname)
with open(fpath, 'wb+') as destination:
for chunk in value.chunks():
destination.write(chunk)
value._name = fname
elif isinstance(field, forms.FileField): # value should be None
fname = self.obj.settings.get(name, as_type=File)
value = None
if fname:
try:
os.unlink(fname.name)
except OSError:
logger.error('Deleting file %s failed.' % fname.name)
if value is None: if value is None:
del self.obj.settings[name] del self.obj.settings[name]
elif self.obj.settings.get(name, as_type=type(value)) != value: elif self.obj.settings.get(name, as_type=type(value)) != value:
+26 -8
View File
@@ -1,9 +1,12 @@
import decimal import decimal
import json import json
import os
from datetime import date, datetime, time from datetime import date, datetime, time
from urllib.parse import urljoin
import dateutil.parser import dateutil.parser
from django.conf import settings from django.conf import settings
from django.core.files import File
from django.db.models import Model from django.db.models import Model
from versions.models import Versionable from versions.models import Versionable
@@ -134,6 +137,14 @@ class SettingsProxy:
return json.loads(value) return json.loads(value)
elif as_type == bool or value in ('True', 'False'): elif as_type == bool or value in ('True', 'False'):
return value == 'True' return value == 'True'
elif as_type == File:
try:
f = open(os.path.join(settings.MEDIA_ROOT, value[7:]), 'r')
fi = File(f)
fi.url = urljoin(settings.MEDIA_URL, value[7:])
return fi
except OSError:
return False
elif as_type == datetime: elif as_type == datetime:
return dateutil.parser.parse(value) return dateutil.parser.parse(value)
elif as_type == date: elif as_type == date:
@@ -160,6 +171,8 @@ class SettingsProxy:
return value.identity return value.identity
elif isinstance(value, Model): elif isinstance(value, Model):
return value.pk return value.pk
elif isinstance(value, File):
return 'file://' + value.name
raise TypeError('Unable to serialize %s into a setting.' % str(type(value))) raise TypeError('Unable to serialize %s into a setting.' % str(type(value)))
@@ -173,14 +186,19 @@ class SettingsProxy:
as_type = DEFAULTS[key]['type'] as_type = DEFAULTS[key]['type']
if key in self._cache(): if key in self._cache():
return self._unserialize(self._cache()[key].value, as_type) value = self._cache()[key].value
value = None else:
if self._parent: value = None
value = self._parent.settings.get(key) if self._parent:
if value is None and key in DEFAULTS: value = self._parent.settings.get(key)
return self._unserialize(DEFAULTS[key]['default'], as_type) if value is None and key in DEFAULTS:
if value is None and default is not None: value = DEFAULTS[key]['default']
return self._unserialize(default, as_type) if value is None and default is not None:
value = default
if as_type is None and value is not None and value.startswith('file://'):
as_type = File
return self._unserialize(value, as_type) return self._unserialize(value, as_type)
def __getitem__(self, key): def __getitem__(self, key):
+19
View File
@@ -1,3 +1,4 @@
import os
from functools import partial from functools import partial
from itertools import product from itertools import product
@@ -403,3 +404,21 @@ class VariationsField(forms.ModelMultipleChoiceField):
return cleaned_value return cleaned_value
choices = property(_get_choices, forms.ChoiceField._set_choices) choices = property(_get_choices, forms.ChoiceField._set_choices)
class ExtFileField(forms.FileField):
def __init__(self, *args, **kwargs):
ext_whitelist = kwargs.pop("ext_whitelist")
self.ext_whitelist = [i.lower() for i in ext_whitelist]
super().__init__(*args, **kwargs)
def clean(self, *args, **kwargs):
data = super().clean(*args, **kwargs)
if data:
filename = data.name
ext = os.path.splitext(filename)[1]
ext = ext.lower()
if ext not in self.ext_whitelist:
raise forms.ValidationError(_("Filetype not allowed!"))
return data
-2
View File
@@ -185,7 +185,6 @@ class ProviderForm(SettingsForm):
for k, v in self.fields.items(): for k, v in self.fields.items():
val = cleaned_data.get(k) val = cleaned_data.get(k)
if v._required and (val is None or val == ""): if v._required and (val is None or val == ""):
print(enabled, k, v)
self.add_error(k, _('This field is required.')) self.add_error(k, _('This field is required.'))
@@ -217,5 +216,4 @@ class TicketSettingsForm(SettingsForm):
for k, v in self.fields.items(): for k, v in self.fields.items():
val = cleaned_data.get(k) val = cleaned_data.get(k)
if v._required and (val is None or val == ""): if v._required and (val is None or val == ""):
print(enabled, k, v)
self.add_error(k, _('This field is required.')) self.add_error(k, _('This field is required.'))
@@ -2,7 +2,7 @@
{% load i18n %} {% load i18n %}
{% load bootstrap3 %} {% load bootstrap3 %}
{% block inside %} {% block inside %}
<form action="" method="post" class="form-horizontal"> <form action="" method="post" class="form-horizontal" enctype="multipart/form-data">
{% csrf_token %} {% csrf_token %}
<fieldset> <fieldset>
<legend>{% trans "Ticket download" %}</legend> <legend>{% trans "Ticket download" %}</legend>
+2 -1
View File
@@ -231,7 +231,8 @@ class TicketSettings(EventPermissionRequiredMixin, FormView):
provider.form = ProviderForm( provider.form = ProviderForm(
obj=self.request.event, obj=self.request.event,
settingspref='ticketoutput_%s_' % provider.identifier, settingspref='ticketoutput_%s_' % provider.identifier,
data=(self.request.POST if self.request.method == 'POST' else None) data=(self.request.POST if self.request.method == 'POST' else None),
files=(self.request.FILES if self.request.method == 'POST' else None)
) )
provider.form.fields = OrderedDict( provider.form.fields = OrderedDict(
[ [
@@ -8,6 +8,7 @@ from django.http import HttpResponse
from django.utils.translation import ugettext_lazy as _ from django.utils.translation import ugettext_lazy as _
from pretix.base.ticketoutput import BaseTicketOutput from pretix.base.ticketoutput import BaseTicketOutput
from pretix.control.forms import ExtFileField
logger = logging.getLogger('pretix.plugins.ticketoutputpdf') logger = logging.getLogger('pretix.plugins.ticketoutputpdf')
@@ -112,5 +113,11 @@ class PdfTicketOutput(BaseTicketOutput):
), ),
required=False required=False
)), )),
('background',
ExtFileField(
label=_('Background PDF'),
ext_whitelist=(".pdf", ),
required=False
)),
] ]
) )