]> git.0d.be Git - panikdb.git/blob - panikdb/emissions/forms.py
e2645e03d5bd6a98fddf8eaaf0fc19203850715f
[panikdb.git] / panikdb / emissions / forms.py
1 import datetime
2 import re
3 import unicodedata
4 import os
5 import uuid
6
7 from django import forms
8 from django.forms import fields
9
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.conf import settings
14 from django.template.loader import render_to_string
15
16 from taggit.forms import TagWidget
17
18
19 from .models import Emission, Episode, Diffusion, Schedule, SoundFile
20
21
22 def slugify(s):
23     s = unicodedata.normalize('NFKD', s).encode('ascii', 'ignore').lower()
24     return re.sub(r'\W+', '-', s)
25
26
27 class DayAndHourWidget(forms.MultiWidget):
28     def __init__(self, attrs=None):
29         WEEKDAYS = [u'Lundi', u'Mardi', u'Mercredi', u'Jeudi', u'Vendredi', u'Samedi', u'Dimanche']
30         widgets = (
31             forms.Select(attrs=attrs, choices=([(weekday, WEEKDAYS[weekday]) for weekday in range(7)])),
32             forms.Select(attrs=attrs, choices=([(hour, hour) for hour in range(24)])),
33             forms.Select(attrs=attrs, choices=([(minute, str(minute).zfill(2)) for minute in range(60)])),
34         )
35         super(DayAndHourWidget, self).__init__(widgets, attrs)
36
37     def decompress(self, value):
38         if value:
39             return [value.weekday(), value.hour, value.minute]
40         return [None, None, None]
41
42     def value_from_datadict(self, data, files, name):
43         # we only care about day/hour/minutes, but we conveniently use a
44         # datetime value to store that; we pick 2007 as reference year as
45         # it had its January 1st on a Monday.
46         data_list = [
47             widget.value_from_datadict(data, files, name + '_%s' % i)
48             for i, widget in enumerate(self.widgets)]
49
50         if data_list:
51             return datetime.datetime(2007, 1, int(data_list[0])+1, int(data_list[1]), int(data_list[2]))
52         return None
53
54
55 class JqueryFileUploadFileInput(forms.FileInput):
56     def render(self, name, value, attrs=None):
57         output = render_to_string('emissions/upload.html', {
58             'upload_url': self.url,
59             'files': self.files,
60             'name': name,
61             'STATIC_URL': settings.STATIC_URL})
62         return mark_safe(output)
63
64
65 class JqueryFileUploadInput(forms.MultiWidget):
66     needs_multipart_form = True
67     upload_id_re = re.compile(r'^[a-z0-9A-Z-]+$')
68     upload_id = None
69
70     def __init__(self, attrs=None, choices=[], max_filename_length=None):
71         self.max_filename_length = max_filename_length
72         widget_list = (forms.HiddenInput(attrs=attrs),
73                 JqueryFileUploadFileInput(attrs=attrs))
74         super(JqueryFileUploadInput, self).__init__(widget_list, attrs)
75
76     def decompress(self, value):
77         # map python value to widget contents
78         if self.upload_id:
79             pass
80         elif isinstance(value, (list, tuple)) and value and value[0] is not None:
81             self.upload_id = str(value[0])
82         else:
83             self.upload_id = str(uuid.uuid4())
84         return [self.upload_id, None]
85
86     def get_files_for_id(self, upload_id):
87         storage = DefaultStorage()
88         path = os.path.join('upload', upload_id)
89         if not storage.exists(path):
90             return
91         for filepath in storage.listdir(path)[1]:
92             name = os.path.basename(filepath)
93             yield storage.open(os.path.join(path, name))
94
95     def value_from_datadict(self, data, files, name):
96         '''
97            If some file was submitted, that's the value,
98            If a regular hidden_id is present, use it to find uploaded files,
99            otherwise return an empty list
100         '''
101         upload_id, file_input = super(JqueryFileUploadInput, self).value_from_datadict(data, files, name)
102         if file_input:
103             pass
104         elif JqueryFileUploadInput.upload_id_re.match(upload_id):
105             file_input = list(self.get_files_for_id(upload_id))
106         else:
107             file_input = []
108         return file_input[0]
109
110     def render(self, name, value, attrs=None):
111         self.decompress(value)
112         self.widgets[1].url = '/upload/%s/' % self.upload_id
113         self.widgets[1].url = reverse('upload', kwargs={'transaction_id': self.upload_id})
114         if self.max_filename_length:
115             self.widgets[1].url += '?max_filename_length=%d' % self.max_filename_length
116         self.widgets[1].files = '/upload/%s/' % self.get_files_for_id(self.upload_id)
117         output = super(JqueryFileUploadInput, self).render(name, value,
118                 attrs)
119         fileinput_id = '%s_%s' % (attrs['id'], '1')
120         return output
121
122
123 class EmissionForm(forms.ModelForm):
124     class Meta:
125         model = Emission
126         exclude = ('slug',)
127
128     def save(self, commit=True):
129         if not self.instance.slug:
130             self.instance.slug = slugify(self.instance.title)
131         return super(EmissionForm, self).save(commit=commit)
132
133
134 class EpisodeForm(forms.ModelForm):
135     class Meta:
136         model = Episode
137         exclude = ('slug',)
138         widgets = {'emission': forms.HiddenInput(),
139                    'tags': TagWidget()}
140
141     def save(self, commit=True):
142         if not self.instance.slug:
143             self.instance.slug = slugify(self.instance.title)
144         return super(EpisodeForm, self).save(commit=commit)
145
146
147 class EpisodeNewForm(EpisodeForm):
148     diffusion = forms.DateTimeField()
149
150     def save(self, commit=True):
151         episode = super(EpisodeNewForm, self).save(commit=commit)
152         diffusion = Diffusion()
153         diffusion.episode_id = episode.id
154         diffusion.datetime = self.cleaned_data.get('diffusion')
155         diffusion.save()
156         return episode
157
158
159 class ScheduleForm(forms.ModelForm):
160     class Meta:
161         model = Schedule
162         widgets = {
163                 'emission': forms.HiddenInput(),
164                 'datetime': DayAndHourWidget(),
165         }
166
167
168 class SoundFileForm(forms.ModelForm):
169     class Meta:
170         model = SoundFile
171         widgets = {
172                 'episode': forms.HiddenInput(),
173                 'file': JqueryFileUploadInput(),
174         }
175
176
177 class DiffusionForm(forms.ModelForm):
178     class Meta:
179         model = Diffusion
180         widgets = {
181                 'episode': forms.HiddenInput(),
182         }