forms.py 7.37 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
11
import logging

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

Skia's avatar
Skia committed
14

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
# 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

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

69
# Forms
Skia's avatar
Skia committed
70
71
72
73
74
75

class RegisteringForm(UserCreationForm):
    error_css_class = 'error'
    required_css_class = 'required'
    class Meta:
        model = User
76
        fields = ('first_name', 'last_name', 'email')
Skia's avatar
Skia committed
77
78
79
80
81
82
83
84
85

    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

86
from core.utils import resize_image
Skia's avatar
Skia committed
87
88
89
from io import BytesIO
from PIL import Image

90
91
92
93
94
95
96
97
98
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
99
100
                '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
101
                'forum_signature', 'is_subscriber_viewable']
102
103
104
105
106
        widgets = {
                'date_of_birth': SelectDate,
                'profile_pict': forms.ClearableFileInput,
                'avatar_pict': forms.ClearableFileInput,
                'scrub_pict': forms.ClearableFileInput,
Skia's avatar
Skia committed
107
108
                'phone': PhoneNumberInternationalFallbackWidget,
                'parent_phone': PhoneNumberInternationalFallbackWidget,
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
                }
        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
138
139
140
141
142
                    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
143
144
145
146
147
148
149
150
151
152
153
                    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
154
155
156
157
                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")})
158
        self._post_clean()
Skia's avatar
Skia committed
159

Skia's avatar
Skia committed
160
class UserPropForm(forms.ModelForm):
Skia's avatar
Skia committed
161
162
163
164
    error_css_class = 'error'
    required_css_class = 'required'
    class Meta:
        model = User
165
        fields = ['groups']
Skia's avatar
Skia committed
166
167
168
        help_texts = {
            'groups': "Which groups this user belongs to",
        }
Skia's avatar
Skia committed
169
170
171
        widgets = {
            'groups': CheckboxSelectMultiple,
        }
Skia's avatar
Skia committed
172

173
174
175
176
177
class PagePropForm(forms.ModelForm):
    error_css_class = 'error'
    required_css_class = 'required'
    class Meta:
        model = Page
Skia's avatar
Skia committed
178
        fields = ['parent', 'name', 'owner_group', 'edit_groups', 'view_groups', ]
179
        widgets = {
Skia's avatar
Skia committed
180
181
            'edit_groups': CheckboxSelectMultiple,
            'view_groups': CheckboxSelectMultiple,
182
183
        }

Skia's avatar
Skia committed
184
185
    def __init__(self, *arg, **kwargs):
        super(PagePropForm, self).__init__(*arg, **kwargs)
Skia's avatar
Skia committed
186
187
        self.fields['edit_groups'].required = False
        self.fields['view_groups'].required = False
Skia's avatar
Skia committed
188