annotate bio/forms.py @ 741:9aae4f99f062

Django 1.6: ModelForms should use either fields or exclude.
author Brian Neal <bgneal@gmail.com>
date Sun, 29 Dec 2013 13:20:07 -0600
parents 5be850a66dfc
children 4f265f61874b
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
bgneal@612 14 import pytz
bgneal@612 15
gremmie@1 16 from bio.models import UserProfile
bgneal@149 17 from core.widgets import AutoCompleteUserInput
bgneal@265 18 from core.image import parse_image, downscale_image_square
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."""
bgneal@609 31 location = forms.CharField(required=False, widget=forms.TextInput(attrs={'size': 64 }))
bgneal@609 32 occupation = forms.CharField(required=False, widget=forms.TextInput(attrs={'size': 64 }))
bgneal@609 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@312 36 profile_text = forms.CharField(required=False,
bgneal@390 37 widget=forms.Textarea(attrs={'class': 'markItUp'}))
bgneal@312 38 signature = forms.CharField(required=False,
bgneal@390 39 widget=forms.Textarea(attrs={'class': 'markItUp'}))
bgneal@390 40 auto_favorite = forms.BooleanField(
bgneal@390 41 label='Automatically favorite every forum topic I create or reply to', required=False)
bgneal@390 42 auto_subscribe = forms.BooleanField(
bgneal@390 43 label='Automatically subscribe to every forum topic I create or reply to', required=False)
gremmie@1 44
gremmie@1 45 class Meta:
gremmie@1 46 model = UserProfile
bgneal@609 47 fields = ('location', 'country', 'birthday', 'occupation', 'interests',
bgneal@206 48 'profile_text', 'hide_email', 'signature', 'time_zone',
bgneal@390 49 'use_24_time', 'auto_favorite', 'auto_subscribe')
gremmie@1 50
gremmie@1 51 class Media:
gremmie@1 52 css = {
bgneal@484 53 'all': (settings.GPP_THIRD_PARTY_CSS['markitup'] +
bgneal@484 54 settings.GPP_THIRD_PARTY_CSS['jquery-ui'])
gremmie@1 55 }
bgneal@484 56 js = (settings.GPP_THIRD_PARTY_JS['markitup'] +
bgneal@484 57 settings.GPP_THIRD_PARTY_JS['jquery-ui'] +
bgneal@484 58 ['js/bio.js', 'js/timezone.js'])
gremmie@1 59
bgneal@612 60 def clean_time_zone(self):
bgneal@612 61 """Ensure the timezone is valid and will work with pytz.
bgneal@612 62
bgneal@612 63 A blank (empty) value is allowed.
bgneal@612 64 """
bgneal@612 65
bgneal@612 66 tz = self.cleaned_data['time_zone'].strip()
bgneal@612 67 if tz:
bgneal@612 68 try:
bgneal@612 69 pytz.timezone(tz)
bgneal@612 70 except pytz.UnknownTimeZoneError:
bgneal@612 71 raise forms.ValidationError('Invalid timezone')
bgneal@612 72
bgneal@612 73 return tz
bgneal@612 74
gremmie@1 75
gremmie@1 76 class UploadAvatarForm(forms.Form):
gremmie@1 77 """Form used to change a user's avatar"""
gremmie@1 78 avatar_file = forms.ImageField(required=False)
gremmie@1 79 image = None
gremmie@1 80
gremmie@1 81 def clean_avatar_file(self):
bgneal@265 82 f = self.cleaned_data['avatar_file']
bgneal@265 83 if f is not None:
bgneal@265 84 if f.size > settings.MAX_AVATAR_SIZE_BYTES:
bgneal@265 85 raise forms.ValidationError("Please upload a file smaller than "
bgneal@338 86 "%s bytes." % settings.MAX_AVATAR_SIZE_BYTES)
bgneal@265 87 try:
bgneal@265 88 self.image = parse_image(f)
bgneal@265 89 except IOError:
bgneal@265 90 raise forms.ValidationError("Please upload a valid image. "
bgneal@265 91 "The file you uploaded was either not an image or a "
bgneal@265 92 "corrupted image.")
bgneal@265 93 self.file_type = self.image.format
bgneal@265 94 return f
gremmie@1 95
bgneal@265 96 def save(self):
bgneal@265 97 """
bgneal@265 98 Perform any down-scaling needed on the new file, then return a tuple of
bgneal@265 99 (filename, file object). Note that the file object returned may not
bgneal@265 100 have a name; use the returned filename instead.
bgneal@265 101
bgneal@265 102 """
bgneal@265 103 if not self.cleaned_data['avatar_file']:
bgneal@265 104 return None, None
bgneal@265 105
bgneal@265 106 name = self.cleaned_data['avatar_file'].name
bgneal@265 107 dim = settings.MAX_AVATAR_SIZE_PIXELS
bgneal@265 108 max_size = (dim, dim)
bgneal@265 109 if self.image and self.image.size > max_size:
bgneal@265 110 self.image = downscale_image_square(self.image, dim)
bgneal@265 111
bgneal@265 112 # We need to return a Django File now. To get that from here,
bgneal@265 113 # write the image data info a StringIO and then construct a
bgneal@265 114 # Django ContentFile from that. The ContentFile has no name,
bgneal@265 115 # that is why we return one ourselves explicitly.
gremmie@1 116 s = StringIO()
bgneal@265 117 self.image.save(s, self.file_type)
bgneal@265 118 return name, ContentFile(s.getvalue())
bgneal@312 119
bgneal@265 120 return name, self.cleaned_data['avatar_file']
gremmie@1 121
bgneal@149 122
bgneal@149 123 class SearchUsersForm(forms.Form):
bgneal@149 124 """
bgneal@149 125 A form to search for users.
bgneal@149 126 """
bgneal@149 127 username = forms.CharField(max_length=30, widget=AutoCompleteUserInput())
bgneal@149 128
bgneal@197 129 class Media:
bgneal@197 130 css = {
bgneal@197 131 'all': settings.GPP_THIRD_PARTY_CSS['jquery-ui']
bgneal@197 132 }
bgneal@197 133 js = settings.GPP_THIRD_PARTY_JS['jquery-ui']
bgneal@197 134
bgneal@149 135 def clean_username(self):
bgneal@463 136 username = self.cleaned_data['username'].strip()
bgneal@149 137 try:
bgneal@149 138 User.objects.get(username=username, is_active=True)
bgneal@149 139 except User.DoesNotExist:
bgneal@149 140 raise forms.ValidationError("That username does not exist.")
bgneal@149 141 return username