forms.py 8.27 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
6
from django.forms import CheckboxSelectMultiple, Select, DateInput, TextInput
Skia's avatar
Skia committed
7
from django.utils.translation import ugettext as _
Skia's avatar
Skia committed
8
9
from phonenumber_field.widgets import PhoneNumberInternationalFallbackWidget

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

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

Skia's avatar
Skia committed
15

16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
# 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)

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

56
57
58
59
60
61
62
63
64
65
66
67
68
69
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

70
# Forms
Skia's avatar
Skia committed
71

Skia's avatar
Skia committed
72
73
74
75
76
77
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
78
79
80
81
82
83
84
            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
85
                data['username'] = user.username
Skia's avatar
Skia committed
86
            except: pass
Skia's avatar
Skia committed
87
88
89
90
            kwargs['data'] = data
        super(LoginForm, self).__init__(*arg, **kwargs)
        self.fields['username'].label = _("Username, email, or account number")

Skia's avatar
Skia committed
91
92
93
94
95
class RegisteringForm(UserCreationForm):
    error_css_class = 'error'
    required_css_class = 'required'
    class Meta:
        model = User
96
        fields = ('first_name', 'last_name', 'email')
Skia's avatar
Skia committed
97
98
99
100
101
102
103
104
105

    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

106
from core.utils import resize_image
Skia's avatar
Skia committed
107
108
109
from io import BytesIO
from PIL import Image

110
111
112
113
114
115
116
117
118
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
119
120
                '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
121
                'forum_signature', 'is_subscriber_viewable']
122
123
124
125
126
        widgets = {
                'date_of_birth': SelectDate,
                'profile_pict': forms.ClearableFileInput,
                'avatar_pict': forms.ClearableFileInput,
                'scrub_pict': forms.ClearableFileInput,
Skia's avatar
Skia committed
127
128
                'phone': PhoneNumberInternationalFallbackWidget,
                'parent_phone': PhoneNumberInternationalFallbackWidget,
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
                }
        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
158
159
160
161
162
                    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
163
164
165
166
167
168
169
170
171
172
173
                    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
174
175
176
177
                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")})
178
        self._post_clean()
Skia's avatar
Skia committed
179

Skia's avatar
Skia committed
180
class UserPropForm(forms.ModelForm):
Skia's avatar
Skia committed
181
182
183
184
    error_css_class = 'error'
    required_css_class = 'required'
    class Meta:
        model = User
185
        fields = ['groups']
Skia's avatar
Skia committed
186
187
188
        help_texts = {
            'groups': "Which groups this user belongs to",
        }
Skia's avatar
Skia committed
189
190
191
        widgets = {
            'groups': CheckboxSelectMultiple,
        }
Skia's avatar
Skia committed
192

193
194
195
196
197
class PagePropForm(forms.ModelForm):
    error_css_class = 'error'
    required_css_class = 'required'
    class Meta:
        model = Page
Skia's avatar
Skia committed
198
        fields = ['parent', 'name', 'owner_group', 'edit_groups', 'view_groups', ]
199
        widgets = {
Skia's avatar
Skia committed
200
201
            'edit_groups': CheckboxSelectMultiple,
            'view_groups': CheckboxSelectMultiple,
202
203
        }

Skia's avatar
Skia committed
204
205
    def __init__(self, *arg, **kwargs):
        super(PagePropForm, self).__init__(*arg, **kwargs)
Skia's avatar
Skia committed
206
207
        self.fields['edit_groups'].required = False
        self.fields['view_groups'].required = False
Skia's avatar
Skia committed
208