forms.py 8.89 KB
Newer Older
Skia's avatar
Skia committed
1
from django.contrib.auth.forms import UserCreationForm, AuthenticationForm, UserChangeForm
Skia's avatar
Skia committed
2
from django import forms
3
4
from django.db import transaction
from django.core.exceptions import ValidationError
Skia's avatar
Skia committed
5
from django.contrib.auth import logout, login, authenticate
Skia's avatar
Skia committed
6
from django.forms import CheckboxSelectMultiple, Select, DateInput, TextInput, DateTimeInput
Skia's avatar
Skia committed
7
from django.utils.translation import ugettext as _
Skia's avatar
Skia committed
8
from phonenumber_field.widgets import PhoneNumberInternationalFallbackWidget
Skia's avatar
Skia committed
9
from ajax_select.fields import AutoCompleteSelectField
Skia's avatar
Skia committed
10

Skia's avatar
Skia committed
11
import logging
Skia's avatar
Skia committed
12
import re
Skia's avatar
Skia committed
13

14
15
from core.models import User, Page, RealGroup, SithFile

Skia's avatar
Skia committed
16

17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
# Widgets

class SelectSingle(Select):
    def render(self, name, value, attrs=None):
        if attrs:
            attrs['class'] = "select_single"
        else:
            attrs = {'class': "select_single"}
        return super(SelectSingle, self).render(name, value, attrs)

class SelectMultiple(Select):
    def render(self, name, value, attrs=None):
        if attrs:
            attrs['class'] = "select_multiple"
        else:
            attrs = {'class': "select_multiple"}
        return super(SelectMultiple, self).render(name, value, attrs)

Skia's avatar
Skia committed
35
36
37
38
39
40
41
42
class SelectDateTime(DateTimeInput):
    def render(self, name, value, attrs=None):
        if attrs:
            attrs['class'] = "select_datetime"
        else:
            attrs = {'class': "select_datetime"}
        return super(SelectDateTime, self).render(name, value, attrs)

43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
class SelectDate(DateInput):
    def render(self, name, value, attrs=None):
        if attrs:
            attrs['class'] = "select_date"
        else:
            attrs = {'class': "select_date"}
        return super(SelectDate, self).render(name, value, attrs)

class SelectFile(TextInput):
    def render(self, name, value, attrs=None):
        if attrs:
            attrs['class'] = "select_file"
        else:
            attrs = {'class': "select_file"}
        output = '%(content)s<div name="%(name)s" class="choose_file_widget" title="%(title)s"></div>' % {
                'content': super(SelectFile, self).render(name, value, attrs),
                'title': _("Choose file"),
                'name': name,
                }
        output += '<span name="' + name + '" class="choose_file_button">' + _("Choose file") + '</span>'
        return output

65
66
67
68
69
70
71
72
73
74
75
76
77
78
class SelectUser(TextInput):
    def render(self, name, value, attrs=None):
        if attrs:
            attrs['class'] = "select_user"
        else:
            attrs = {'class': "select_user"}
        output = '%(content)s<div name="%(name)s" class="choose_user_widget" title="%(title)s"></div>' % {
                'content': super(SelectUser, self).render(name, value, attrs),
                'title': _("Choose user"),
                'name': name,
                }
        output += '<span name="' + name + '" class="choose_user_button">' + _("Choose user") + '</span>'
        return output

79
# Forms
Skia's avatar
Skia committed
80

Skia's avatar
Skia committed
81
82
83
84
85
86
class LoginForm(AuthenticationForm):
    def __init__(self, *arg, **kwargs):
        if 'data' in kwargs.keys():
            from counter.models import Customer
            data = kwargs['data'].copy()
            account_code = re.compile(r"^[0-9]+[A-Za-z]$")
Skia's avatar
Skia committed
87
88
89
90
91
92
93
            try:
                if account_code.match(data['username']):
                    user = Customer.objects.filter(account_id__iexact=data['username']).first().user
                elif '@' in data['username']:
                    user = User.objects.filter(email__iexact=data['username']).first()
                else:
                    user = User.objects.filter(username=data['username']).first()
Skia's avatar
Skia committed
94
                data['username'] = user.username
Skia's avatar
Skia committed
95
            except: pass
Skia's avatar
Skia committed
96
97
98
99
            kwargs['data'] = data
        super(LoginForm, self).__init__(*arg, **kwargs)
        self.fields['username'].label = _("Username, email, or account number")

Skia's avatar
Skia committed
100
101
102
103
104
class RegisteringForm(UserCreationForm):
    error_css_class = 'error'
    required_css_class = 'required'
    class Meta:
        model = User
105
        fields = ('first_name', 'last_name', 'email')
Skia's avatar
Skia committed
106
107
108
109
110
111
112
113
114

    def save(self, commit=True):
        user = super(RegisteringForm, self).save(commit=False)
        user.set_password(self.cleaned_data["password1"])
        user.generate_username()
        if commit:
            user.save()
        return user

115
from core.utils import resize_image
Skia's avatar
Skia committed
116
117
118
from io import BytesIO
from PIL import Image

119
120
121
122
123
124
125
126
127
class UserProfileForm(forms.ModelForm):
    """
    Form handling the user profile, managing the files
    This form is actually pretty bad and was made in the rush before the migration. It should be refactored.
    TODO: refactor this form
    """
    class Meta:
        model = User
        fields = ['first_name', 'last_name', 'nick_name', 'email', 'date_of_birth', 'profile_pict', 'avatar_pict',
Skia's avatar
Skia committed
128
129
                'scrub_pict', 'sex', 'second_email', 'address', 'parent_address', 'phone', 'parent_phone',
                'tshirt_size', 'role', 'department', 'dpt_option', 'semester', 'quote', 'school', 'promo',
Sli's avatar
Sli committed
130
                'forum_signature', 'is_subscriber_viewable', 'is_banned_alcohol']
131
132
133
134
135
        widgets = {
                'date_of_birth': SelectDate,
                'profile_pict': forms.ClearableFileInput,
                'avatar_pict': forms.ClearableFileInput,
                'scrub_pict': forms.ClearableFileInput,
Skia's avatar
Skia committed
136
137
                'phone': PhoneNumberInternationalFallbackWidget,
                'parent_phone': PhoneNumberInternationalFallbackWidget,
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
                }
        labels = {
                'profile_pict': _("Profile: you need to be visible on the picture, in order to be recognized (e.g. by the barmen)"),
                'avatar_pict': _("Avatar: used on the forum"),
                'scrub_pict': _("Scrub: let other know how your scrub looks like!"),
                }

    def __init__(self, *arg, **kwargs):
        super(UserProfileForm, self).__init__(*arg, **kwargs)

    def full_clean(self):
        super(UserProfileForm, self).full_clean()

    def generate_name(self, field_name, f):
        field_name = field_name[:-4]
        return field_name + str(self.instance.id) + "." + f.content_type.split('/')[-1]

    def process(self, files):
        avatar = self.instance.avatar_pict
        profile = self.instance.profile_pict
        scrub = self.instance.scrub_pict
        self.full_clean()
        self.cleaned_data['avatar_pict'] = avatar
        self.cleaned_data['profile_pict'] = profile
        self.cleaned_data['scrub_pict'] = scrub
        parent = SithFile.objects.filter(parent=None, name="profiles").first()
        for field,f in files:
            with transaction.atomic():
                try:
Skia's avatar
Skia committed
167
168
169
170
171
                    im = Image.open(BytesIO(f.read()))
                    new_file = SithFile(parent=parent, name=self.generate_name(field, f),
                            file=resize_image(im, 400, f.content_type.split('/')[-1]),
                            owner=self.instance, is_folder=False, mime_type=f.content_type, size=f._size)
                    new_file.file.name = new_file.name
172
173
174
175
176
177
178
179
180
181
182
                    old = SithFile.objects.filter(parent=parent, name=new_file.name).first()
                    if old:
                        old.delete()
                    new_file.clean()
                    new_file.save()
                    self.cleaned_data[field] = new_file
                    self._errors.pop(field, None)
                except ValidationError as e:
                    self._errors.pop(field, None)
                    self.add_error(field, _("Error uploading file %(file_name)s: %(msg)s") %
                            {'file_name': f, 'msg': str(e.message)})
Skia's avatar
Skia committed
183
184
185
186
                except IOError:
                    self._errors.pop(field, None)
                    self.add_error(field, _("Error uploading file %(file_name)s: %(msg)s") %
                            {'file_name': f, 'msg': _("Bad image format, only jpeg, png, and gif are accepted")})
187
        self._post_clean()
Skia's avatar
Skia committed
188

Skia's avatar
Skia committed
189
class UserPropForm(forms.ModelForm):
Skia's avatar
Skia committed
190
191
192
193
    error_css_class = 'error'
    required_css_class = 'required'
    class Meta:
        model = User
194
        fields = ['groups']
Skia's avatar
Skia committed
195
196
197
        help_texts = {
            'groups': "Which groups this user belongs to",
        }
Skia's avatar
Skia committed
198
199
200
        widgets = {
            'groups': CheckboxSelectMultiple,
        }
Skia's avatar
Skia committed
201

Skia's avatar
Skia committed
202
203
204
205
class UserGodfathersForm(forms.Form):
    type = forms.ChoiceField(choices=[('godfather', _("Godfather")), ('godchild', _("Godchild"))], label=_("Add"))
    user = AutoCompleteSelectField('users', required=True, label=_("Select user"), help_text=None)

206
207
208
209
210
class PagePropForm(forms.ModelForm):
    error_css_class = 'error'
    required_css_class = 'required'
    class Meta:
        model = Page
Skia's avatar
Skia committed
211
        fields = ['parent', 'name', 'owner_group', 'edit_groups', 'view_groups', ]
212
        widgets = {
Skia's avatar
Skia committed
213
214
            'edit_groups': CheckboxSelectMultiple,
            'view_groups': CheckboxSelectMultiple,
215
216
        }

Skia's avatar
Skia committed
217
218
    def __init__(self, *arg, **kwargs):
        super(PagePropForm, self).__init__(*arg, **kwargs)
Skia's avatar
Skia committed
219
220
        self.fields['edit_groups'].required = False
        self.fields['view_groups'].required = False
Skia's avatar
Skia committed
221