forms.py 5.11 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
from django.utils.translation import ugettext_lazy as _
9
# third party imports
Daniel W Bond's avatar
Daniel W Bond committed
10
from multiselectfield import MultiSelectFormField
11
from haystack.forms import SearchForm
12
# imports from your apps
13
14
15
16
17
from .models import Student, Major
from housing.models import Building, Floor, Room


class SelectRoomWidget(forms.widgets.Select):
18
    """A series of dropdowns in which a student can filter through housing options."""
19
20
21

    template_name = 'room_select_widget.html'

22
    def __init__(self, user=None, attrs=None, rooms=None, floors=None, buildings=None, neighborhoods=None):
23
24
25
26
        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.")
27
        # should probably type check the other fields too
28
        if rooms is None:
29
            self.rooms = Room.objects.all().prefetch_related('floor')
30
31
32
33
        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:
34
            self.floors = Floor.objects.all().prefetch_related('building')
35
36
37
38
39
40
        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):
41
        context = {
42
43
44
            'neighborhoods': self.neighborhoods,
            'buildings': self.buildings,
            'floors': self.floors,
45
            'rooms': self.rooms,
46
        }
47
48
        if self.user is not None:
            context['user'] = self.user
49
        return mark_safe(render_to_string(self.template_name, context))
50

Daniel W Bond's avatar
Daniel W Bond committed
51

Daniel W Bond's avatar
Daniel W Bond committed
52
class SelectRoomField(forms.models.ModelChoiceField):
53
    """A special field for room selection, using the room selection widget."""
Daniel W Bond's avatar
Daniel W Bond committed
54
55
    widget = SelectRoomWidget

56
57
#    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
58

59
60

class BooleanRadioField(forms.TypedChoiceField):
61
    """Displays booleans as a radio selector, rather than checkboxes."""
62
63
64
65
66
67
68
69
70
71
72

    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)


73
class StudentUpdateForm(forms.Form):
74

75
76
    first_name = forms.CharField(required=False, max_length=30)
    last_name = forms.CharField(required=False, max_length=30)
77
    gender = MultiSelectFormField(choices=Student.GENDER_CHOICES,
78
                                  required=False)
79
    show_gender = BooleanRadioField(required=True)
80

81
    on_campus = BooleanRadioField(required=True)
82
    room = SelectRoomField(queryset=Room.objects.all(), required=False)
83

84
    privacy = forms.TypedChoiceField(choices=Student.PRIVACY_CHOICES)
85
    # exclude self from request in form instantiation
Daniel W Bond's avatar
Daniel W Bond committed
86
87
88
    blocked_kids = forms.ModelMultipleChoiceField(queryset=Student.objects.all(),
                                                  required=False)

89
    major = forms.ModelMultipleChoiceField(queryset=Major.objects.all(), required=False)
90
    graduating_year = forms.IntegerField(max_value=9999, min_value=-9999, required=False)
91

92
93
94
    def clean(self):
        cleaned_data = super(StudentUpdateForm, self).clean()
        form_room = cleaned_data.get('room')
95
96
        if not(form_room is None):
            students_in_room = Student.objects.filter(room=form_room).count()
Daniel W Bond's avatar
pep8 me    
Daniel W Bond committed
97
            # print(students_in_room)
98
99
100
            # 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')
101

Daniel W Bond's avatar
Daniel W Bond committed
102
    def is_valid(self):
103
        # errors are not printed in form.as_p?
Daniel W Bond's avatar
pep8 me    
Daniel W Bond committed
104
105
106
        # 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
107
        valid = super(StudentUpdateForm, self).is_valid()
Daniel W Bond's avatar
pep8 me    
Daniel W Bond committed
108
        # print(valid)
Daniel W Bond's avatar
Daniel W Bond committed
109
        return valid
110
111
112
113


class FarewellFeedbackForm(forms.Form):

114
    # required = True by default
115
    leaving = BooleanRadioField(label="Are you graduating or leaving Mason?")
116
    feedback = forms.CharField(label="Thoughts",
117
                               max_length=1000,
118
119
                               widget=forms.Textarea(attrs={'class': 'form-control'}),
                               required=False)
120
121
122
123
124
125
126
127


# we are overwriting the search form to include boostrap css classes
class AccountSearchForm(SearchForm):

    q = forms.CharField(required=False, label=_('Search'),
                        widget=forms.TextInput(attrs={'type': 'search',
                                                      'class': 'form-control'}))