forms.py 9 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_lazy as _
Sli's avatar
Sli committed
8
from django.utils.translation import ugettext
Skia's avatar
Skia committed
9
from phonenumber_field.widgets import PhoneNumberInternationalFallbackWidget
Skia's avatar
Skia committed
10
from ajax_select.fields import AutoCompleteSelectField
Skia's avatar
Skia committed
11

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

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

Skia's avatar
Skia committed
17

18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
# 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
36
37
38
39
40
41
42
43
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)

44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
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,
                }
Sli's avatar
Sli committed
63
        output += '<span name="' + name + '" class="choose_file_button">' + ugettext("Choose file") + '</span>'
64
65
        return output

66
67
68
69
70
71
72
73
74
75
76
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,
                }
Sli's avatar
Sli committed
77
        output += '<span name="' + name + '" class="choose_user_button">' + ugettext("Choose user") + '</span>'
78
79
        return output

80
# Forms
Skia's avatar
Skia committed
81

Skia's avatar
Skia committed
82
83
84
85
86
87
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
88
89
90
91
92
93
94
            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
95
                data['username'] = user.username
Skia's avatar
Skia committed
96
            except: pass
Skia's avatar
Skia committed
97
98
99
100
            kwargs['data'] = data
        super(LoginForm, self).__init__(*arg, **kwargs)
        self.fields['username'].label = _("Username, email, or account number")

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

    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

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

120
121
122
123
124
125
126
127
128
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
129
130
                'scrub_pict', 'sex', 'second_email', 'address', 'parent_address', 'phone', 'parent_phone',
                'tshirt_size', 'role', 'department', 'dpt_option', 'semester', 'quote', 'school', 'promo',
Skia's avatar
Skia committed
131
                'forum_signature', 'is_subscriber_viewable']
132
133
134
135
136
        widgets = {
                'date_of_birth': SelectDate,
                'profile_pict': forms.ClearableFileInput,
                'avatar_pict': forms.ClearableFileInput,
                'scrub_pict': forms.ClearableFileInput,
Skia's avatar
Skia committed
137
138
                'phone': PhoneNumberInternationalFallbackWidget,
                'parent_phone': PhoneNumberInternationalFallbackWidget,
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
167
                }
        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
168
169
170
                    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]),
Skia's avatar
Skia committed
171
172
                            owner=self.instance, is_folder=False, mime_type=f.content_type, size=f._size,
                            moderator=self.instance, is_moderated=True)
Skia's avatar
Skia committed
173
                    new_file.file.name = new_file.name
174
175
176
177
178
179
180
181
182
183
184
                    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
185
186
187
188
                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")})
189
        self._post_clean()
Skia's avatar
Skia committed
190

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

Skia's avatar
Skia committed
204
205
206
207
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)

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

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