updates for stage 2
[edumed.git] / stage2 / forms.py
1 # -*- coding: utf-8 -*-
2 from decimal import Decimal
3
4 from django import forms
5 from django.core import validators
6 from django.template.defaultfilters import filesizeformat
7 from django.utils.safestring import mark_safe
8
9 from stage2.models import Attachment, Mark, FieldOptionSet, FieldOption
10
11
12 class AttachmentForm(forms.ModelForm):
13     assignment_id = forms.CharField(widget=forms.HiddenInput)
14
15     class Meta:
16         model = Attachment
17         fields = ['file']
18
19     def __init__(self, assignment, file_no, label, options, *args, **kwargs):
20         prefix = 'att%s-%s' % (assignment.id, file_no)
21         super(AttachmentForm, self).__init__(*args, prefix=prefix, **kwargs)
22         self.fields['assignment_id'].initial = assignment.id
23         extensions = options.get('ext')
24         max_mb = options.get('max', 20)
25         self.max_upload_size = max_mb * 1024 * 1024
26         self.fields['file'].widget.attrs['data-max'] = max_mb
27         self.fields['file'].label = label + u' (maks. %s MB)' % max_mb
28         if extensions:
29             self.fields['file'].widget.attrs['data-ext'] = '|'.join(extensions)
30         self.extensions = extensions
31
32     def clean_file(self):
33         file = self.cleaned_data['file']
34         if file.size > self.max_upload_size:
35             raise forms.ValidationError(
36                 u'Prosimy o wysłanie pliku o rozmiarze najwyżej %s. Aktualny rozmiar pliku: %s' % (
37                     filesizeformat(self.max_upload_size), filesizeformat(file.size)))
38         if self.extensions and ('.' not in file.name or file.name.rsplit('.', 1)[1].lower() not in self.extensions):
39             raise forms.ValidationError(u'Niepoprawne rozszerzenie, powinno być jedno z: %s' % ', '.join(self.extensions))
40         return file
41
42
43 class AssignmentFieldForm(forms.Form):
44     value = forms.CharField(required=False)
45     assignment_id = forms.CharField(widget=forms.HiddenInput)
46
47     def __init__(self, label, field_no, options, answer, *args, **kwargs):
48         prefix = 'field%s-%s' % (answer.id, field_no)
49         super(AssignmentFieldForm, self).__init__(prefix=prefix, *args, **kwargs)
50         self.answer = answer
51         self.label = label
52         self.fields['value'].label = label
53         self.type = options['type']
54         self.fields['assignment_id'].initial = answer.assignment.id
55         max_length = options.get('max_length')
56         if max_length:
57             self.fields['value'].validators.append(validators.MaxLengthValidator(int(max_length)))
58             self.fields['value'].label += u' (maks. %s znaków)' % max_length
59         if options.get('widget') == 'area':
60             self.fields['value'].widget = forms.Textarea(attrs={'cols': 80, 'rows': 25})
61         if self.type == 'options':
62             option_set = FieldOptionSet.objects.get(name=options['option_set'])
63             self.fields['value'].widget = forms.Select(choices=option_set.choices(answer))
64             value_options = answer.fieldoption_set.all()
65             if value_options:
66                 self.fields['value'].initial = value_options.get().id
67         else:
68             value = answer.field_values.get(label)
69             self.fields['value'].initial = value or ''
70
71     def clean_value(self):
72         if self.type == 'options':
73             value = self.cleaned_data['value']
74             if value:
75                 try:
76                     option = FieldOption.objects.get(id=int(value))
77                 except (FieldOption.DoesNotExist, ValueError):
78                     raise forms.ValidationError(u'Nieprawidłowa wartość.')
79                 if option.answer != self.answer and option.answer is not None:
80                     raise forms.ValidationError(u'Ta opcja została już wybrana przez kogoś innego.')
81                 return option
82         return self.cleaned_data['value']
83
84     def save(self):
85         value = self.cleaned_data['value']
86         if self.type == 'options':
87             option = value
88             if option:
89                 if option.answer != self.answer:
90                     # not thread-safe :/
91                     assert not option.answer
92                     for opt in self.answer.fieldoption_set.all():
93                         opt.answer = None
94                         opt.save()
95                     option.answer = self.answer
96                     option.save()
97             else:
98                 for opt in self.answer.fieldoption_set.all():
99                     opt.answer = None
100                     opt.save()
101         else:
102             self.answer.field_values[self.label] = value
103             self.answer.save()
104
105
106 class MarkForm(forms.ModelForm):
107     answer_id = forms.CharField(widget=forms.HiddenInput)
108
109     class Meta:
110         model = Mark
111         fields = ['points']
112         widgets = {
113             'points': forms.TextInput(attrs={'type': 'number', 'min': 0, 'step': '0.5'})
114         }
115
116     def __init__(self, answer, criterion, *args, **kwargs):
117         super(MarkForm, self).__init__(*args, **kwargs)
118         self.fields['answer_id'].initial = answer.id
119         points_field = self.fields['points']
120         points_field.label = mark_safe(criterion.form_label())
121         points_field.help_text = '(max %s)' % criterion.max_points
122         points_field.min_value = Decimal(0)
123         points_field.max_value = Decimal(criterion.max_points)
124         points_field.widget.attrs['max'] = criterion.max_points