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