annotate gpp/bio/forms.py @ 197:2baadae33f2e

Got autocomplete working for the member search. Updated django and ran into a bug where url tags with comma separated kwargs starting consuming tons of CPU throughput. The work-around is to cut over to using spaces between arguments. This is now allowed to be consistent with other tags. Did some query optimization for the news app.
author Brian Neal <bgneal@gmail.com>
date Sat, 10 Apr 2010 04:32:24 +0000
parents ab7830b067b3
children 272d3a8c98e8
rev   line source
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@120 43 exclude = ('user', 'avatar', 'profile_html', 'signature_html', 'forum_post_count')
gremmie@1 44
gremmie@1 45 class Media:
gremmie@1 46 css = {
bgneal@6 47 'all': settings.GPP_THIRD_PARTY_CSS['markitup'] + \
bgneal@6 48 settings.GPP_THIRD_PARTY_CSS['jquery-ui']
gremmie@1 49 }
bgneal@12 50 js = settings.GPP_THIRD_PARTY_JS['markitup'] + \
bgneal@6 51 settings.GPP_THIRD_PARTY_JS['jquery-ui'] + \
bgneal@70 52 ('js/bio.js', 'js/timezone.js')
gremmie@1 53
gremmie@1 54
gremmie@1 55 def get_image(file):
gremmie@1 56 """
gremmie@1 57 Returns a PIL Image from the supplied file.
gremmie@1 58 Throws ValidationError if the file does not parse as an image file.
gremmie@1 59 """
gremmie@1 60 parser = ImageFile.Parser()
gremmie@1 61 for chunk in file.chunks():
gremmie@1 62 parser.feed(chunk)
gremmie@1 63 try:
gremmie@1 64 image = parser.close()
gremmie@1 65 return image
gremmie@1 66 except IOError:
gremmie@1 67 pass
gremmie@1 68 raise forms.ValidationError("Upload a valid image. " +
gremmie@1 69 "The file you uploaded was either not an image or a corrupted image.")
gremmie@1 70
gremmie@1 71
gremmie@1 72 def scale_image(image, size):
gremmie@1 73 """Scales an image file if necessary."""
gremmie@1 74
gremmie@1 75 # don't upscale
gremmie@1 76 if (size, size) >= image.size:
gremmie@1 77 return image
gremmie@1 78
gremmie@1 79 (w, h) = image.size
gremmie@1 80 if w > h:
gremmie@1 81 diff = (w - h) / 2
gremmie@1 82 image = image.crop((diff, 0, w - diff, h))
gremmie@1 83 elif h > w:
gremmie@1 84 diff = (h - w) / 2
gremmie@1 85 image = image.crop((0, diff, w, h - diff))
gremmie@1 86 image = image.resize((size, size), Image.ANTIALIAS)
gremmie@1 87 return image
gremmie@1 88
gremmie@1 89
gremmie@1 90 class UploadAvatarForm(forms.Form):
gremmie@1 91 """Form used to change a user's avatar"""
gremmie@1 92 avatar_file = forms.ImageField(required=False)
gremmie@1 93 image = None
gremmie@1 94
gremmie@1 95 def clean_avatar_file(self):
gremmie@1 96 file = self.cleaned_data['avatar_file']
gremmie@1 97 if file is not None:
gremmie@1 98 if file.size > settings.MAX_AVATAR_SIZE_BYTES:
gremmie@1 99 raise forms.ValidationError("Please upload a file smaller than %s bytes." % \
gremmie@1 100 settings.MAX_AVATAR_SIZE)
gremmie@1 101 self.image = get_image(file)
gremmie@1 102 self.format = self.image.format
gremmie@1 103 return file
gremmie@1 104
gremmie@1 105 def get_file(self):
gremmie@1 106 if self.image is not None:
gremmie@1 107 self.image = scale_image(self.image, settings.MAX_AVATAR_SIZE_PIXELS)
gremmie@1 108 s = StringIO()
gremmie@1 109 self.image.save(s, self.format)
gremmie@1 110 return ContentFile(s.getvalue())
gremmie@1 111 return None
gremmie@1 112
gremmie@1 113 def get_filename(self):
gremmie@1 114 return self.cleaned_data['avatar_file'].name
gremmie@1 115
bgneal@149 116
bgneal@149 117 class SearchUsersForm(forms.Form):
bgneal@149 118 """
bgneal@149 119 A form to search for users.
bgneal@149 120 """
bgneal@149 121 username = forms.CharField(max_length=30, widget=AutoCompleteUserInput())
bgneal@149 122
bgneal@197 123 class Media:
bgneal@197 124 css = {
bgneal@197 125 'all': settings.GPP_THIRD_PARTY_CSS['jquery-ui']
bgneal@197 126 }
bgneal@197 127 js = settings.GPP_THIRD_PARTY_JS['jquery-ui']
bgneal@197 128
bgneal@149 129 def clean_username(self):
bgneal@149 130 username = self.cleaned_data['username']
bgneal@149 131 try:
bgneal@149 132 User.objects.get(username=username, is_active=True)
bgneal@149 133 except User.DoesNotExist:
bgneal@149 134 raise forms.ValidationError("That username does not exist.")
bgneal@149 135 return username