gremmie@1
|
1 """
|
gremmie@1
|
2 This file contains the forms used by the bio application.
|
gremmie@1
|
3 """
|
gremmie@1
|
4 from PIL import ImageFile
|
gremmie@1
|
5 from PIL import Image
|
gremmie@1
|
6
|
gremmie@1
|
7 try:
|
gremmie@1
|
8 from cStringIO import StringIO
|
gremmie@1
|
9 except:
|
gremmie@1
|
10 from StringIO import StringIO
|
gremmie@1
|
11
|
gremmie@1
|
12 from django import forms
|
gremmie@1
|
13 from django.conf import settings
|
gremmie@1
|
14 from django.core.files.base import ContentFile
|
gremmie@1
|
15 from django.contrib.auth.models import User
|
gremmie@1
|
16
|
gremmie@1
|
17 from bio.models import UserProfile
|
bgneal@149
|
18 from core.widgets import AutoCompleteUserInput
|
gremmie@1
|
19
|
gremmie@1
|
20
|
gremmie@1
|
21 class EditUserForm(forms.ModelForm):
|
gremmie@1
|
22 """Form for editing the fields of the User model."""
|
gremmie@1
|
23 email = forms.EmailField(label='Email', required=True)
|
gremmie@1
|
24 class Meta:
|
gremmie@1
|
25 model = User
|
gremmie@1
|
26 fields = ('first_name', 'last_name', 'email')
|
gremmie@1
|
27
|
gremmie@1
|
28
|
gremmie@1
|
29 class EditUserProfileForm(forms.ModelForm):
|
gremmie@1
|
30 """Form for editing the fields of the UserProfile model."""
|
gremmie@1
|
31 location = forms.CharField(required=False, widget=forms.TextInput(attrs={'size' : 64 }))
|
gremmie@1
|
32 occupation = forms.CharField(required=False, widget=forms.TextInput(attrs={'size' : 64 }))
|
gremmie@1
|
33 interests = forms.CharField(required=False, widget=forms.TextInput(attrs={'size' : 64 }))
|
bgneal@70
|
34 time_zone = forms.CharField(required=False, widget=forms.HiddenInput())
|
bgneal@120
|
35 use_24_time = forms.BooleanField(label='Show times in 24-hour mode', required=False)
|
bgneal@133
|
36 profile_text = forms.CharField(required=False,
|
bgneal@133
|
37 widget=forms.Textarea(attrs={'class': 'markItUp'}))
|
bgneal@133
|
38 signature = forms.CharField(required=False,
|
bgneal@133
|
39 widget=forms.Textarea(attrs={'class': 'markItUp'}))
|
gremmie@1
|
40
|
gremmie@1
|
41 class Meta:
|
gremmie@1
|
42 model = UserProfile
|
bgneal@206
|
43 fields = ('location', 'birthday', 'occupation', 'interests',
|
bgneal@206
|
44 'profile_text', 'hide_email', 'signature', 'time_zone',
|
bgneal@206
|
45 'use_24_time', )
|
gremmie@1
|
46
|
gremmie@1
|
47 class Media:
|
gremmie@1
|
48 css = {
|
bgneal@6
|
49 'all': settings.GPP_THIRD_PARTY_CSS['markitup'] + \
|
bgneal@6
|
50 settings.GPP_THIRD_PARTY_CSS['jquery-ui']
|
gremmie@1
|
51 }
|
bgneal@12
|
52 js = settings.GPP_THIRD_PARTY_JS['markitup'] + \
|
bgneal@6
|
53 settings.GPP_THIRD_PARTY_JS['jquery-ui'] + \
|
bgneal@70
|
54 ('js/bio.js', 'js/timezone.js')
|
gremmie@1
|
55
|
gremmie@1
|
56
|
gremmie@1
|
57 def get_image(file):
|
gremmie@1
|
58 """
|
gremmie@1
|
59 Returns a PIL Image from the supplied file.
|
gremmie@1
|
60 Throws ValidationError if the file does not parse as an image file.
|
gremmie@1
|
61 """
|
gremmie@1
|
62 parser = ImageFile.Parser()
|
gremmie@1
|
63 for chunk in file.chunks():
|
gremmie@1
|
64 parser.feed(chunk)
|
gremmie@1
|
65 try:
|
gremmie@1
|
66 image = parser.close()
|
gremmie@1
|
67 return image
|
gremmie@1
|
68 except IOError:
|
gremmie@1
|
69 pass
|
gremmie@1
|
70 raise forms.ValidationError("Upload a valid image. " +
|
gremmie@1
|
71 "The file you uploaded was either not an image or a corrupted image.")
|
gremmie@1
|
72
|
gremmie@1
|
73
|
gremmie@1
|
74 def scale_image(image, size):
|
gremmie@1
|
75 """Scales an image file if necessary."""
|
gremmie@1
|
76
|
gremmie@1
|
77 # don't upscale
|
gremmie@1
|
78 if (size, size) >= image.size:
|
gremmie@1
|
79 return image
|
gremmie@1
|
80
|
gremmie@1
|
81 (w, h) = image.size
|
gremmie@1
|
82 if w > h:
|
gremmie@1
|
83 diff = (w - h) / 2
|
gremmie@1
|
84 image = image.crop((diff, 0, w - diff, h))
|
gremmie@1
|
85 elif h > w:
|
gremmie@1
|
86 diff = (h - w) / 2
|
gremmie@1
|
87 image = image.crop((0, diff, w, h - diff))
|
gremmie@1
|
88 image = image.resize((size, size), Image.ANTIALIAS)
|
gremmie@1
|
89 return image
|
gremmie@1
|
90
|
gremmie@1
|
91
|
gremmie@1
|
92 class UploadAvatarForm(forms.Form):
|
gremmie@1
|
93 """Form used to change a user's avatar"""
|
gremmie@1
|
94 avatar_file = forms.ImageField(required=False)
|
gremmie@1
|
95 image = None
|
gremmie@1
|
96
|
gremmie@1
|
97 def clean_avatar_file(self):
|
gremmie@1
|
98 file = self.cleaned_data['avatar_file']
|
gremmie@1
|
99 if file is not None:
|
gremmie@1
|
100 if file.size > settings.MAX_AVATAR_SIZE_BYTES:
|
gremmie@1
|
101 raise forms.ValidationError("Please upload a file smaller than %s bytes." % \
|
gremmie@1
|
102 settings.MAX_AVATAR_SIZE)
|
gremmie@1
|
103 self.image = get_image(file)
|
gremmie@1
|
104 self.format = self.image.format
|
gremmie@1
|
105 return file
|
gremmie@1
|
106
|
gremmie@1
|
107 def get_file(self):
|
gremmie@1
|
108 if self.image is not None:
|
gremmie@1
|
109 self.image = scale_image(self.image, settings.MAX_AVATAR_SIZE_PIXELS)
|
gremmie@1
|
110 s = StringIO()
|
gremmie@1
|
111 self.image.save(s, self.format)
|
gremmie@1
|
112 return ContentFile(s.getvalue())
|
gremmie@1
|
113 return None
|
gremmie@1
|
114
|
gremmie@1
|
115 def get_filename(self):
|
gremmie@1
|
116 return self.cleaned_data['avatar_file'].name
|
gremmie@1
|
117
|
bgneal@149
|
118
|
bgneal@149
|
119 class SearchUsersForm(forms.Form):
|
bgneal@149
|
120 """
|
bgneal@149
|
121 A form to search for users.
|
bgneal@149
|
122 """
|
bgneal@149
|
123 username = forms.CharField(max_length=30, widget=AutoCompleteUserInput())
|
bgneal@149
|
124
|
bgneal@197
|
125 class Media:
|
bgneal@197
|
126 css = {
|
bgneal@197
|
127 'all': settings.GPP_THIRD_PARTY_CSS['jquery-ui']
|
bgneal@197
|
128 }
|
bgneal@197
|
129 js = settings.GPP_THIRD_PARTY_JS['jquery-ui']
|
bgneal@197
|
130
|
bgneal@149
|
131 def clean_username(self):
|
bgneal@149
|
132 username = self.cleaned_data['username']
|
bgneal@149
|
133 try:
|
bgneal@149
|
134 User.objects.get(username=username, is_active=True)
|
bgneal@149
|
135 except User.DoesNotExist:
|
bgneal@149
|
136 raise forms.ValidationError("That username does not exist.")
|
bgneal@149
|
137 return username
|