annotate gpp/bio/forms.py @ 505:a5d11471d031

Refactor the logic in the rate limiter decorator. Check to see if the request was ajax, as the ajax view always returns 200. Have to decode the JSON response to see if an error occurred or not.
author Brian Neal <bgneal@gmail.com>
date Sat, 03 Dec 2011 19:13:38 +0000
parents bbbc357ac5f3
children
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 try:
gremmie@1 5 from cStringIO import StringIO
gremmie@1 6 except:
gremmie@1 7 from StringIO import StringIO
gremmie@1 8
gremmie@1 9 from django import forms
gremmie@1 10 from django.conf import settings
gremmie@1 11 from django.core.files.base import ContentFile
gremmie@1 12 from django.contrib.auth.models import User
gremmie@1 13
gremmie@1 14 from bio.models import UserProfile
bgneal@149 15 from core.widgets import AutoCompleteUserInput
bgneal@265 16 from core.image import parse_image, downscale_image_square
gremmie@1 17
gremmie@1 18
gremmie@1 19 class EditUserForm(forms.ModelForm):
gremmie@1 20 """Form for editing the fields of the User model."""
gremmie@1 21 email = forms.EmailField(label='Email', required=True)
gremmie@1 22 class Meta:
gremmie@1 23 model = User
gremmie@1 24 fields = ('first_name', 'last_name', 'email')
gremmie@1 25
gremmie@1 26
gremmie@1 27 class EditUserProfileForm(forms.ModelForm):
gremmie@1 28 """Form for editing the fields of the UserProfile model."""
gremmie@1 29 location = forms.CharField(required=False, widget=forms.TextInput(attrs={'size' : 64 }))
gremmie@1 30 occupation = forms.CharField(required=False, widget=forms.TextInput(attrs={'size' : 64 }))
gremmie@1 31 interests = forms.CharField(required=False, widget=forms.TextInput(attrs={'size' : 64 }))
bgneal@70 32 time_zone = forms.CharField(required=False, widget=forms.HiddenInput())
bgneal@120 33 use_24_time = forms.BooleanField(label='Show times in 24-hour mode', required=False)
bgneal@312 34 profile_text = forms.CharField(required=False,
bgneal@390 35 widget=forms.Textarea(attrs={'class': 'markItUp'}))
bgneal@312 36 signature = forms.CharField(required=False,
bgneal@390 37 widget=forms.Textarea(attrs={'class': 'markItUp'}))
bgneal@390 38 auto_favorite = forms.BooleanField(
bgneal@390 39 label='Automatically favorite every forum topic I create or reply to', required=False)
bgneal@390 40 auto_subscribe = forms.BooleanField(
bgneal@390 41 label='Automatically subscribe to every forum topic I create or reply to', required=False)
gremmie@1 42
gremmie@1 43 class Meta:
gremmie@1 44 model = UserProfile
bgneal@206 45 fields = ('location', 'birthday', 'occupation', 'interests',
bgneal@206 46 'profile_text', 'hide_email', 'signature', 'time_zone',
bgneal@390 47 'use_24_time', 'auto_favorite', 'auto_subscribe')
gremmie@1 48
gremmie@1 49 class Media:
gremmie@1 50 css = {
bgneal@484 51 'all': (settings.GPP_THIRD_PARTY_CSS['markitup'] +
bgneal@484 52 settings.GPP_THIRD_PARTY_CSS['jquery-ui'])
gremmie@1 53 }
bgneal@484 54 js = (settings.GPP_THIRD_PARTY_JS['markitup'] +
bgneal@484 55 settings.GPP_THIRD_PARTY_JS['jquery-ui'] +
bgneal@484 56 ['js/bio.js', 'js/timezone.js'])
gremmie@1 57
gremmie@1 58
gremmie@1 59 class UploadAvatarForm(forms.Form):
gremmie@1 60 """Form used to change a user's avatar"""
gremmie@1 61 avatar_file = forms.ImageField(required=False)
gremmie@1 62 image = None
gremmie@1 63
gremmie@1 64 def clean_avatar_file(self):
bgneal@265 65 f = self.cleaned_data['avatar_file']
bgneal@265 66 if f is not None:
bgneal@265 67 if f.size > settings.MAX_AVATAR_SIZE_BYTES:
bgneal@265 68 raise forms.ValidationError("Please upload a file smaller than "
bgneal@338 69 "%s bytes." % settings.MAX_AVATAR_SIZE_BYTES)
bgneal@265 70 try:
bgneal@265 71 self.image = parse_image(f)
bgneal@265 72 except IOError:
bgneal@265 73 raise forms.ValidationError("Please upload a valid image. "
bgneal@265 74 "The file you uploaded was either not an image or a "
bgneal@265 75 "corrupted image.")
bgneal@265 76 self.file_type = self.image.format
bgneal@265 77 return f
gremmie@1 78
bgneal@265 79 def save(self):
bgneal@265 80 """
bgneal@265 81 Perform any down-scaling needed on the new file, then return a tuple of
bgneal@265 82 (filename, file object). Note that the file object returned may not
bgneal@265 83 have a name; use the returned filename instead.
bgneal@265 84
bgneal@265 85 """
bgneal@265 86 if not self.cleaned_data['avatar_file']:
bgneal@265 87 return None, None
bgneal@265 88
bgneal@265 89 name = self.cleaned_data['avatar_file'].name
bgneal@265 90 dim = settings.MAX_AVATAR_SIZE_PIXELS
bgneal@265 91 max_size = (dim, dim)
bgneal@265 92 if self.image and self.image.size > max_size:
bgneal@265 93 self.image = downscale_image_square(self.image, dim)
bgneal@265 94
bgneal@265 95 # We need to return a Django File now. To get that from here,
bgneal@265 96 # write the image data info a StringIO and then construct a
bgneal@265 97 # Django ContentFile from that. The ContentFile has no name,
bgneal@265 98 # that is why we return one ourselves explicitly.
gremmie@1 99 s = StringIO()
bgneal@265 100 self.image.save(s, self.file_type)
bgneal@265 101 return name, ContentFile(s.getvalue())
bgneal@312 102
bgneal@265 103 return name, self.cleaned_data['avatar_file']
gremmie@1 104
bgneal@149 105
bgneal@149 106 class SearchUsersForm(forms.Form):
bgneal@149 107 """
bgneal@149 108 A form to search for users.
bgneal@149 109 """
bgneal@149 110 username = forms.CharField(max_length=30, widget=AutoCompleteUserInput())
bgneal@149 111
bgneal@197 112 class Media:
bgneal@197 113 css = {
bgneal@197 114 'all': settings.GPP_THIRD_PARTY_CSS['jquery-ui']
bgneal@197 115 }
bgneal@197 116 js = settings.GPP_THIRD_PARTY_JS['jquery-ui']
bgneal@197 117
bgneal@149 118 def clean_username(self):
bgneal@463 119 username = self.cleaned_data['username'].strip()
bgneal@149 120 try:
bgneal@149 121 User.objects.get(username=username, is_active=True)
bgneal@149 122 except User.DoesNotExist:
bgneal@149 123 raise forms.ValidationError("That username does not exist.")
bgneal@149 124 return username