forms.py 3.73 KB
Newer Older
1
2
# standard library imports
from __future__ import absolute_import, print_function
3
# core django imports
4
from django import forms
5
6
from django.utils.safestring import mark_safe
from django.template.loader import render_to_string
Daniel W Bond's avatar
Daniel W Bond committed
7
from django.core.exceptions import ValidationError
8
# third party imports
Daniel W Bond's avatar
Daniel W Bond committed
9
from multiselectfield import MultiSelectFormField
10
# imports from your apps
11
12
13
14
15
16
17
18
from .models import Student, Major
from housing.models import Building, Floor, Room


class SelectRoomWidget(forms.widgets.Select):

    template_name = 'room_select_widget.html'

19
    def __init__(self, user=None, attrs=None, rooms=None, floors=None, buildings=None, neighborhoods=None):
20
21
22
23
        super(SelectRoomWidget, self).__init__(attrs)
        # attrs to be implemented later (allows specifying css class, for example)
        if attrs:
            print("Sorry about that, but we're currently ignoring your fancy attrs.")
24
        # should probably type check the other fields too
25
26
        if rooms is None:
            self.rooms = Room.objects.all()
27
28
29
30
31
32
33
34
35
36
37
        else:
            if not all(isinstance(thing, Room) for thing in rooms):
                raise TypeError("Rooms in a SelectRoomWidget must all be Rooms!")
        if floors is None:
            self.floors = Floor.objects.all()
        if buildings is None:
            self.buildings = Building.objects.all()
        if neighborhoods is None:
            self.neighborhoods = Building.NEIGHBOURHOOD_CHOICES

    def render(self, name, value, attrs=None):
38
        context = {
39
40
41
            'neighborhoods': self.neighborhoods,
            'buildings': self.buildings,
            'floors': self.floors,
42
            'rooms': self.rooms,
43
        }
44
45
        if self.user is not None:
            context['user'] = self.user
46
        return mark_safe(render_to_string(self.template_name, context))
47

Daniel W Bond's avatar
Daniel W Bond committed
48

Daniel W Bond's avatar
Daniel W Bond committed
49
50
51
class SelectRoomField(forms.models.ModelChoiceField):
    widget = SelectRoomWidget

52
53
#    should raise error if user hasn't actually selected room, made it to end of selectors
#    def clean(self, value):
Daniel W Bond's avatar
Daniel W Bond committed
54

55
56
57
58
59
60
61
62
63
64
65
66
67

class BooleanRadioField(forms.TypedChoiceField):

    def __init__(self, *args, **kwargs):
        boolean_choices = ((True, 'Yes'), (False, 'No'))

        kwargs['widget'] = forms.RadioSelect
        kwargs['choices'] = boolean_choices
        kwargs['coerce'] = bool
        kwargs['required'] = True
        super(BooleanRadioField, self).__init__(*args, **kwargs)


68
class StudentUpdateForm(forms.Form):
69

70
71
    first_name = forms.CharField(required=False)
    last_name = forms.CharField(required=False)
72
    gender = MultiSelectFormField(choices=Student.GENDER_CHOICES,
73
                                  required=False)
74
    show_gender = BooleanRadioField()
75

76
77
    on_campus = BooleanRadioField()
    room = SelectRoomField(queryset=Room.objects.all(), required=False)
78

79
80
81
    privacy = forms.TypedChoiceField(choices=Student.PRIVACY_CHOICES)
    major = forms.ModelChoiceField(queryset=Major.objects.all(), required=False)
    graduating_year = forms.IntegerField()
82

Daniel W Bond's avatar
Daniel W Bond committed
83

84
85
86
    def clean(self):
        cleaned_data = super(StudentUpdateForm, self).clean()
        form_room = cleaned_data.get('room')
87
88
89
90
91
92
        if not(form_room is None):
            students_in_room = Student.objects.filter(room=form_room).count()
            #print(students_in_room)
            # like in bookshare, I have no idea why the form errors don't display.
            if students_in_room > 12:
                raise ValidationError(_('Too many students in room (%d).' % students_in_room), code='invalid')
93

Daniel W Bond's avatar
Daniel W Bond committed
94
    def is_valid(self):
95
96
97
98
        # errors are not printed in form.as_p?
        #print("In is_valid.")
        #print(self.is_bound, 'is bound')
        #print(self.errors, type(self.errors), 'errors')
Daniel W Bond's avatar
Daniel W Bond committed
99
        valid = super(StudentUpdateForm, self).is_valid()
100
        #print(valid)
Daniel W Bond's avatar
Daniel W Bond committed
101
        return valid