gremmie@1: """ gremmie@1: This file contains the forms used by the bio application. gremmie@1: """ gremmie@1: from PIL import ImageFile gremmie@1: from PIL import Image gremmie@1: gremmie@1: try: gremmie@1: from cStringIO import StringIO gremmie@1: except: gremmie@1: from StringIO import StringIO gremmie@1: gremmie@1: from django import forms gremmie@1: from django.conf import settings gremmie@1: from django.core.files.base import ContentFile gremmie@1: from django.contrib.auth.models import User gremmie@1: gremmie@1: from bio.models import UserProfile bgneal@149: from core.widgets import AutoCompleteUserInput gremmie@1: gremmie@1: gremmie@1: class EditUserForm(forms.ModelForm): gremmie@1: """Form for editing the fields of the User model.""" gremmie@1: email = forms.EmailField(label='Email', required=True) gremmie@1: class Meta: gremmie@1: model = User gremmie@1: fields = ('first_name', 'last_name', 'email') gremmie@1: gremmie@1: gremmie@1: class EditUserProfileForm(forms.ModelForm): gremmie@1: """Form for editing the fields of the UserProfile model.""" gremmie@1: location = forms.CharField(required=False, widget=forms.TextInput(attrs={'size' : 64 })) gremmie@1: occupation = forms.CharField(required=False, widget=forms.TextInput(attrs={'size' : 64 })) gremmie@1: interests = forms.CharField(required=False, widget=forms.TextInput(attrs={'size' : 64 })) bgneal@70: time_zone = forms.CharField(required=False, widget=forms.HiddenInput()) bgneal@120: use_24_time = forms.BooleanField(label='Show times in 24-hour mode', required=False) bgneal@133: profile_text = forms.CharField(required=False, bgneal@133: widget=forms.Textarea(attrs={'class': 'markItUp'})) bgneal@133: signature = forms.CharField(required=False, bgneal@133: widget=forms.Textarea(attrs={'class': 'markItUp'})) gremmie@1: gremmie@1: class Meta: gremmie@1: model = UserProfile bgneal@120: exclude = ('user', 'avatar', 'profile_html', 'signature_html', 'forum_post_count') gremmie@1: gremmie@1: class Media: gremmie@1: css = { bgneal@6: 'all': settings.GPP_THIRD_PARTY_CSS['markitup'] + \ bgneal@6: settings.GPP_THIRD_PARTY_CSS['jquery-ui'] gremmie@1: } bgneal@12: js = settings.GPP_THIRD_PARTY_JS['markitup'] + \ bgneal@6: settings.GPP_THIRD_PARTY_JS['jquery-ui'] + \ bgneal@70: ('js/bio.js', 'js/timezone.js') gremmie@1: gremmie@1: gremmie@1: def get_image(file): gremmie@1: """ gremmie@1: Returns a PIL Image from the supplied file. gremmie@1: Throws ValidationError if the file does not parse as an image file. gremmie@1: """ gremmie@1: parser = ImageFile.Parser() gremmie@1: for chunk in file.chunks(): gremmie@1: parser.feed(chunk) gremmie@1: try: gremmie@1: image = parser.close() gremmie@1: return image gremmie@1: except IOError: gremmie@1: pass gremmie@1: raise forms.ValidationError("Upload a valid image. " + gremmie@1: "The file you uploaded was either not an image or a corrupted image.") gremmie@1: gremmie@1: gremmie@1: def scale_image(image, size): gremmie@1: """Scales an image file if necessary.""" gremmie@1: gremmie@1: # don't upscale gremmie@1: if (size, size) >= image.size: gremmie@1: return image gremmie@1: gremmie@1: (w, h) = image.size gremmie@1: if w > h: gremmie@1: diff = (w - h) / 2 gremmie@1: image = image.crop((diff, 0, w - diff, h)) gremmie@1: elif h > w: gremmie@1: diff = (h - w) / 2 gremmie@1: image = image.crop((0, diff, w, h - diff)) gremmie@1: image = image.resize((size, size), Image.ANTIALIAS) gremmie@1: return image gremmie@1: gremmie@1: gremmie@1: class UploadAvatarForm(forms.Form): gremmie@1: """Form used to change a user's avatar""" gremmie@1: avatar_file = forms.ImageField(required=False) gremmie@1: image = None gremmie@1: gremmie@1: def clean_avatar_file(self): gremmie@1: file = self.cleaned_data['avatar_file'] gremmie@1: if file is not None: gremmie@1: if file.size > settings.MAX_AVATAR_SIZE_BYTES: gremmie@1: raise forms.ValidationError("Please upload a file smaller than %s bytes." % \ gremmie@1: settings.MAX_AVATAR_SIZE) gremmie@1: self.image = get_image(file) gremmie@1: self.format = self.image.format gremmie@1: return file gremmie@1: gremmie@1: def get_file(self): gremmie@1: if self.image is not None: gremmie@1: self.image = scale_image(self.image, settings.MAX_AVATAR_SIZE_PIXELS) gremmie@1: s = StringIO() gremmie@1: self.image.save(s, self.format) gremmie@1: return ContentFile(s.getvalue()) gremmie@1: return None gremmie@1: gremmie@1: def get_filename(self): gremmie@1: return self.cleaned_data['avatar_file'].name gremmie@1: bgneal@149: bgneal@149: class SearchUsersForm(forms.Form): bgneal@149: """ bgneal@149: A form to search for users. bgneal@149: """ bgneal@149: username = forms.CharField(max_length=30, widget=AutoCompleteUserInput()) bgneal@149: bgneal@197: class Media: bgneal@197: css = { bgneal@197: 'all': settings.GPP_THIRD_PARTY_CSS['jquery-ui'] bgneal@197: } bgneal@197: js = settings.GPP_THIRD_PARTY_JS['jquery-ui'] bgneal@197: bgneal@149: def clean_username(self): bgneal@149: username = self.cleaned_data['username'] bgneal@149: try: bgneal@149: User.objects.get(username=username, is_active=True) bgneal@149: except User.DoesNotExist: bgneal@149: raise forms.ValidationError("That username does not exist.") bgneal@149: return username