2ef10e53af2f3b3fb079ea216f94a35f3d453f1e
[edumed.git] / stage2 / forms.py
1 # -*- coding: utf-8 -*-
2 from decimal import Decimal
3
4 from django import forms
5 from django.conf import settings
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, extensions=None, *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         self.fields['file'].label = label
24         if extensions:
25             self.fields['file'].widget.attrs = {'data-ext': '|'.join(extensions)}
26         self.extensions = extensions
27
28     def clean_file(self):
29         file = self.cleaned_data['file']
30         if file.size > settings.MAX_UPLOAD_SIZE:
31             raise forms.ValidationError(
32                 'Please keep filesize under %s. Current filesize: %s' % (
33                     filesizeformat(settings.MAX_UPLOAD_SIZE), filesizeformat(file.size)))
34         if self.extensions and ('.' not in file.name or file.name.rsplit('.', 1)[1].lower() not in self.extensions):
35             raise forms.ValidationError('Incorrect extension, should be one of: %s' % ', '.join(self.extensions))
36         return file
37
38
39 class AssignmentFieldForm(forms.Form):
40     value = forms.CharField(required=False)
41     assignment_id = forms.CharField(widget=forms.HiddenInput)
42
43     def __init__(self, label, field_no, options, answer, *args, **kwargs):
44         prefix = 'field%s-%s' % (answer.id, field_no)
45         super(AssignmentFieldForm, self).__init__(prefix=prefix, *args, **kwargs)
46         self.answer = answer
47         self.label = label
48         self.fields['value'].label = label
49         self.type = options['type']
50         self.fields['assignment_id'].initial = answer.assignment.id
51         if self.type == 'options':
52             option_set = FieldOptionSet.objects.get(name=options['option_set'])
53             self.fields['value'].widget = forms.Select(choices=option_set.choices(answer))
54             options = answer.fieldoption_set.all()
55             if options:
56                 self.fields['value'].initial = options.get().id
57         else:
58             value = answer.field_values.get(label)
59             self.fields['value'].initial = value or ''
60
61     def clean_value(self):
62         if self.type == 'options':
63             value = self.cleaned_data['value']
64             if value:
65                 try:
66                     option = FieldOption.objects.get(id=int(value))
67                 except (FieldOption.DoesNotExist, ValueError):
68                     raise forms.ValidationError(u'Nieprawidłowa wartość.')
69                 if option.answer != self.answer and option.answer is not None:
70                     raise forms.ValidationError(u'Ta opcja została już wybrana przez kogoś innego.')
71                 return option
72         return self.cleaned_data['value']
73
74     def save(self):
75         value = self.cleaned_data['value']
76         if self.type == 'options':
77             option = value
78             if option:
79                 if option.answer != self.answer:
80                     # not thread-safe :/
81                     assert not option.answer
82                     for opt in self.answer.fieldoption_set.all():
83                         opt.answer = None
84                         opt.save()
85                     option.answer = self.answer
86                     option.save()
87             else:
88                 for opt in self.answer.fieldoption_set.all():
89                     opt.answer = None
90                     opt.save()
91         else:
92             self.answer.field_values[self.label] = value
93             self.answer.save()
94
95
96 class MarkForm(forms.ModelForm):
97     answer_id = forms.CharField(widget=forms.HiddenInput)
98
99     class Meta:
100         model = Mark
101         fields = ['points']
102         widgets = {
103             'points': forms.TextInput(attrs={'type': 'number', 'min': 0, 'step': '0.5'})
104         }
105
106     def __init__(self, answer, criterion, *args, **kwargs):
107         super(MarkForm, self).__init__(*args, **kwargs)
108         self.fields['answer_id'].initial = answer.id
109         points_field = self.fields['points']
110         points_field.label = mark_safe(criterion.form_label())
111         points_field.help_text = '(max %s)' % criterion.max_points
112         points_field.min_value = Decimal(0)
113         points_field.max_value = Decimal(criterion.max_points)
114         points_field.widget.attrs['max'] = criterion.max_points