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

View File

@@ -1,6 +1,11 @@
import copy
import logging
import os
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.forms.models import BaseModelForm, ModelFormMetaclass
from django.utils import six
@@ -8,6 +13,9 @@ from django.utils.translation import ugettext_lazy as _
from versions.models import Versionable
from pretix.base.i18n import I18nFormField
from pretix.base.models import Event
logger = logging.getLogger('pretix.plugins.ticketoutputpdf')
class BaseI18nModelForm(BaseModelForm):
@@ -89,6 +97,28 @@ class SettingsForm(forms.Form):
def save(self):
for name, field in self.fields.items():
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:
del self.obj.settings[name]
elif self.obj.settings.get(name, as_type=type(value)) != value:

View File

@@ -1,9 +1,12 @@
import decimal
import json
import os
from datetime import date, datetime, time
from urllib.parse import urljoin
import dateutil.parser
from django.conf import settings
from django.core.files import File
from django.db.models import Model
from versions.models import Versionable
@@ -134,6 +137,14 @@ class SettingsProxy:
return json.loads(value)
elif as_type == bool or value in ('True', 'False'):
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:
return dateutil.parser.parse(value)
elif as_type == date:
@@ -160,6 +171,8 @@ class SettingsProxy:
return value.identity
elif isinstance(value, Model):
return value.pk
elif isinstance(value, File):
return 'file://' + value.name
raise TypeError('Unable to serialize %s into a setting.' % str(type(value)))
@@ -173,14 +186,19 @@ class SettingsProxy:
as_type = DEFAULTS[key]['type']
if key in self._cache():
return self._unserialize(self._cache()[key].value, as_type)
value = None
if self._parent:
value = self._parent.settings.get(key)
if value is None and key in DEFAULTS:
return self._unserialize(DEFAULTS[key]['default'], as_type)
if value is None and default is not None:
return self._unserialize(default, as_type)
value = self._cache()[key].value
else:
value = None
if self._parent:
value = self._parent.settings.get(key)
if value is None and key in DEFAULTS:
value = DEFAULTS[key]['default']
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)
def __getitem__(self, key):

View File

@@ -1,3 +1,4 @@
import os
from functools import partial
from itertools import product
@@ -403,3 +404,21 @@ class VariationsField(forms.ModelMultipleChoiceField):
return cleaned_value
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

View File

@@ -185,7 +185,6 @@ class ProviderForm(SettingsForm):
for k, v in self.fields.items():
val = cleaned_data.get(k)
if v._required and (val is None or val == ""):
print(enabled, k, v)
self.add_error(k, _('This field is required.'))
@@ -217,5 +216,4 @@ class TicketSettingsForm(SettingsForm):
for k, v in self.fields.items():
val = cleaned_data.get(k)
if v._required and (val is None or val == ""):
print(enabled, k, v)
self.add_error(k, _('This field is required.'))

View File

@@ -2,7 +2,7 @@
{% load i18n %}
{% load bootstrap3 %}
{% block inside %}
<form action="" method="post" class="form-horizontal">
<form action="" method="post" class="form-horizontal" enctype="multipart/form-data">
{% csrf_token %}
<fieldset>
<legend>{% trans "Ticket download" %}</legend>

View File

@@ -231,7 +231,8 @@ class TicketSettings(EventPermissionRequiredMixin, FormView):
provider.form = ProviderForm(
obj=self.request.event,
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(
[

View File

@@ -8,6 +8,7 @@ from django.http import HttpResponse
from django.utils.translation import ugettext_lazy as _
from pretix.base.ticketoutput import BaseTicketOutput
from pretix.control.forms import ExtFileField
logger = logging.getLogger('pretix.plugins.ticketoutputpdf')
@@ -112,5 +113,11 @@ class PdfTicketOutput(BaseTicketOutput):
),
required=False
)),
('background',
ExtFileField(
label=_('Background PDF'),
ext_whitelist=(".pdf", ),
required=False
)),
]
)