7 from django import forms
8 from django.forms import fields
10 from django.core.files.storage import DefaultStorage
11 from django.core.urlresolvers import reverse
12 from django.utils.safestring import mark_safe
13 from django.utils.translation import ugettext_lazy as _
14 from django.conf import settings
15 from django.template.loader import render_to_string
17 from taggit.forms import TagWidget
18 import datetimewidget.widgets
20 from .models import (Emission, Episode, Diffusion, Schedule, SoundFile,
21 NewsItem, Absence, PlaylistElement)
25 'format': 'dd/mm/yyyy hh:ii',
32 'format': 'dd/mm/yyyy',
40 class DateTimeWidget(datetimewidget.widgets.DateTimeWidget):
41 def __init__(self, *args, **kwargs):
42 super(DateTimeWidget, self).__init__(*args, options=DATETIME_OPTIONS, **kwargs)
44 def format_output(self, rendered_widgets):
45 rendered_widgets[0] += '<span class="add-on"><i class="icon-remove"></i></span>'
46 return super(DateTimeWidget, self).format_output(rendered_widgets)
49 class DateWidget(datetimewidget.widgets.DateTimeWidget):
50 def __init__(self, *args, **kwargs):
51 super(DateWidget, self).__init__(*args, options=DATE_OPTIONS, **kwargs)
53 def format_output(self, rendered_widgets):
54 rendered_widgets[0] += '<span class="add-on"><i class="icon-remove"></i></span>'
55 return super(DateWidget, self).format_output(rendered_widgets)
57 def value_from_datadict(self, data, files, name):
58 t = super(DateWidget, self).value_from_datadict(data, files, name)
60 t = t.split()[0] # date only
65 s = unicodedata.normalize('NFKD', s).encode('ascii', 'ignore').lower()
66 return re.sub(r'\W+', '-', s)
69 class DayAndHourWidget(forms.MultiWidget):
70 def __init__(self, attrs=None):
71 WEEKDAYS = [_('Monday'), _('Tuesday'), _('Wednesday'), _('Thursday'),
72 _('Friday'), _('Saturday'), _('Sunday')]
74 forms.Select(attrs=attrs, choices=([(weekday, WEEKDAYS[weekday]) for weekday in range(7)])),
75 forms.Select(attrs=attrs, choices=([(hour, hour) for hour in range(24)])),
76 forms.Select(attrs=attrs, choices=([(minute, str(minute).zfill(2)) for minute in range(60)])),
78 super(DayAndHourWidget, self).__init__(widgets, attrs)
80 def decompress(self, value):
82 return [value.weekday(), value.hour, value.minute]
83 return [None, None, None]
85 def value_from_datadict(self, data, files, name):
86 # we only care about day/hour/minutes, but we conveniently use a
87 # datetime value to store that; we pick 2007 as reference year as
88 # it had its January 1st on a Monday.
90 widget.value_from_datadict(data, files, name + '_%s' % i)
91 for i, widget in enumerate(self.widgets)]
94 return datetime.datetime(2007, 1, int(data_list[0])+1, int(data_list[1]), int(data_list[2]))
98 class JqueryFileUploadFileInput(forms.FileInput):
99 def render(self, name, value, attrs=None):
100 output = render_to_string('emissions/upload.html', {
101 'upload_url': self.url,
104 'STATIC_URL': settings.STATIC_URL})
105 return mark_safe(output)
108 class JqueryFileUploadInput(forms.MultiWidget):
109 needs_multipart_form = True
110 upload_id_re = re.compile(r'^[a-z0-9A-Z-]+$')
113 def __init__(self, attrs=None, choices=[], max_filename_length=None):
114 self.max_filename_length = max_filename_length
115 widget_list = (forms.HiddenInput(attrs=attrs),
116 JqueryFileUploadFileInput(attrs=attrs))
117 super(JqueryFileUploadInput, self).__init__(widget_list, attrs)
119 def decompress(self, value):
120 # map python value to widget contents
123 elif isinstance(value, (list, tuple)) and value and value[0] is not None:
124 self.upload_id = str(value[0])
126 self.upload_id = str(uuid.uuid4())
127 return [self.upload_id, None]
129 def get_files_for_id(self, upload_id):
130 storage = DefaultStorage()
131 path = os.path.join('upload', upload_id)
132 if not storage.exists(path):
134 for filepath in storage.listdir(path)[1]:
135 name = os.path.basename(filepath)
136 yield storage.open(os.path.join(path, name))
138 def value_from_datadict(self, data, files, name):
140 If some file was submitted, that's the value,
141 If a regular hidden_id is present, use it to find uploaded files,
142 otherwise return an empty list
144 upload_id, file_input = super(JqueryFileUploadInput, self).value_from_datadict(data, files, name)
147 elif JqueryFileUploadInput.upload_id_re.match(upload_id):
148 file_input = list(self.get_files_for_id(upload_id))
156 def render(self, name, value, attrs=None):
157 self.decompress(value)
158 self.widgets[1].url = '/upload/%s/' % self.upload_id
159 self.widgets[1].url = reverse('upload', kwargs={'transaction_id': self.upload_id})
160 if self.max_filename_length:
161 self.widgets[1].url += '?max_filename_length=%d' % self.max_filename_length
162 self.widgets[1].files = '/upload/%s/' % self.get_files_for_id(self.upload_id)
163 output = super(JqueryFileUploadInput, self).render(name, value,
165 fileinput_id = '%s_%s' % (attrs['id'], '1')
169 class EmissionForm(forms.ModelForm):
172 exclude = ('slug', 'colours', 'has_focus', 'got_focus', 'chat_open')
174 def save(self, commit=True):
175 if not self.instance.slug:
176 self.instance.slug = slugify(self.instance.title)
177 return super(EmissionForm, self).save(commit=commit)
180 class EpisodeForm(forms.ModelForm):
183 exclude = ('slug', 'has_focus', 'got_focus', 'effective_start', 'effective_end')
184 widgets = {'emission': forms.HiddenInput(),
187 def save(self, commit=True):
188 if not self.instance.slug:
189 base_slug = slugify(self.instance.title)
194 Episode.objects.get(slug=slug)
195 except Episode.DoesNotExist:
198 slug = '%s-%s' % (base_slug, i)
200 self.instance.slug = slug
201 return super(EpisodeForm, self).save(commit=commit)
204 class EpisodeNewForm(EpisodeForm):
205 first_diffusion = forms.DateTimeField(label=_('First Diffusion'),
206 widget=DateTimeWidget)
207 second_diffusion = forms.DateTimeField(label=_('Second Diffusion'),
208 widget=DateTimeWidget)
209 third_diffusion = forms.DateTimeField(label=_('Third Diffusion'),
210 widget=DateTimeWidget)
211 fourth_diffusion = forms.DateTimeField(label=_('Fourth Diffusion'),
212 widget=DateTimeWidget)
214 def get_diffusion_fields(self, emission):
216 schedules = Schedule.objects.filter(emission=emission, rerun=True).count() + 1
219 fields = ['first_diffusion']
221 fields.append('second_diffusion')
223 fields.append('third_diffusion')
225 fields.append('fourth_diffusion')
228 def __init__(self, *args, **kwargs):
229 super(EpisodeNewForm, self).__init__(*args, **kwargs)
230 emission = kwargs.get('initial', {}).get('emission')
231 diffusion_fields = self.get_diffusion_fields(emission)
232 for field_name in self.fields.keys():
233 if field_name.endswith('_diffusion') and not field_name in diffusion_fields:
234 del self.fields[field_name]
236 def save(self, commit=True):
237 episode = super(EpisodeNewForm, self).save(commit=commit)
238 for field_name in self.get_diffusion_fields(episode.emission):
239 diffusion = Diffusion()
240 diffusion.episode_id = episode.id
241 diffusion.datetime = self.cleaned_data.get(field_name)
246 class ScheduleForm(forms.ModelForm):
250 'emission': forms.HiddenInput(),
251 'datetime': DayAndHourWidget(),
255 class SoundFileForm(forms.ModelForm):
258 exclude = ('has_focus', 'got_focus', 'duration')
260 'episode': forms.HiddenInput(),
261 'file': JqueryFileUploadInput(),
265 class SoundFileEditForm(forms.ModelForm):
268 exclude = ('has_focus', 'got_focus', 'file', 'duration')
270 'episode': forms.HiddenInput(),
273 def __init__(self, *args, **kwargs):
274 super(SoundFileEditForm, self).__init__(*args, **kwargs)
275 self.fields.keyOrder = ['title', 'format', 'podcastable', 'fragment']
278 class DiffusionForm(forms.ModelForm):
282 'episode': forms.HiddenInput(),
283 'datetime': DateTimeWidget(),
287 class NewsItemForm(forms.ModelForm):
290 exclude = ('slug', 'has_focus', 'got_focus')
291 widgets = {'tags': TagWidget(),
292 'date': DateWidget(),
293 'expiration_date': DateWidget(),
294 'event_date': DateWidget(),
297 def __init__(self, *args, **kwargs):
298 super(NewsItemForm, self).__init__(*args, **kwargs)
299 user = kwargs.get('initial', {}).get('user')
300 if not user.is_staff:
301 self.fields['emission'].widget = forms.HiddenInput()
303 def save(self, commit=True):
304 if not self.instance.slug:
305 base_slug = slugify(self.instance.title)
310 NewsItem.objects.get(slug=slug)
311 except NewsItem.DoesNotExist:
314 slug = '%s-%s' % (base_slug, i)
316 self.instance.slug = slug
317 return super(NewsItemForm, self).save(commit=commit)
320 class AbsenceDateTimeWidget(forms.Select):
321 def render_options(self, choices, selected_choices):
326 since = dates[-1] + datetime.timedelta(minutes=10)
329 dates.append(self.emission.get_next_planned_date(since))
330 choices = [(x, x.strftime('%d/%m/%Y %H:%M')) for x in dates]
331 return super(AbsenceDateTimeWidget, self).render_options(choices, selected_choices)
334 class AbsenceForm(forms.ModelForm):
338 'emission': forms.HiddenInput(),
339 'datetime': AbsenceDateTimeWidget(),
342 def __init__(self, *args, **kwargs):
343 super(AbsenceForm, self).__init__(*args, **kwargs)
344 emission = kwargs.get('initial', {}).get('emission')
345 user = kwargs.get('initial', {}).get('user')
346 self.fields['datetime'].widget.emission = emission
347 if user and user.is_staff:
348 date = emission.get_next_planned_date()
349 self.fields['datetime'].initial = date
350 self.fields['datetime'].widget = DateTimeWidget()
352 def save(self, commit=True):
353 t = super(AbsenceForm, self).save(commit=commit)
354 for i, schedule in enumerate(
355 Schedule.objects.filter(emission=self.instance.emission,
356 rerun=True).order_by('datetime')):
357 rerun_date = schedule.get_next_planned_date(self.instance.datetime)
358 rerun_absence = Absence()
359 rerun_absence.emission = self.instance.emission
360 rerun_absence.datetime = rerun_date
365 class PlaylistElementForm(forms.ModelForm):
367 model = PlaylistElement
368 exclude = ('title', 'notes', 'order')
370 'episode': forms.HiddenInput(),
371 'sound': JqueryFileUploadInput(),