annotate bio/forms.py @ 1078:6bf83070b19f

Convert member search to V3 design.
author Brian Neal <bgneal@gmail.com>
date Fri, 22 Apr 2016 22:20:47 -0500
parents 21c592cac71c
children ce6a0c12cbf3
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
bgneal@1078 12 from django.core.urlresolvers import reverse
gremmie@1 13 from django.contrib.auth.models import User
gremmie@1 14
bgneal@612 15 import pytz
bgneal@612 16
gremmie@1 17 from bio.models import UserProfile
bgneal@1011 18 from core.html import image_check
bgneal@1011 19 from core.html import ImageCheckError
bgneal@1011 20 from core.images.utils import parse_image, downscale_image_square
bgneal@1011 21 from core.markup import site_markup
gremmie@1 22
gremmie@1 23
gremmie@1 24 class EditUserForm(forms.ModelForm):
gremmie@1 25 """Form for editing the fields of the User model."""
gremmie@1 26 email = forms.EmailField(label='Email', required=True)
gremmie@1 27 class Meta:
gremmie@1 28 model = User
gremmie@1 29 fields = ('first_name', 'last_name', 'email')
gremmie@1 30
gremmie@1 31
gremmie@1 32 class EditUserProfileForm(forms.ModelForm):
gremmie@1 33 """Form for editing the fields of the UserProfile model."""
bgneal@609 34 location = forms.CharField(required=False, widget=forms.TextInput(attrs={'size': 64 }))
bgneal@609 35 occupation = forms.CharField(required=False, widget=forms.TextInput(attrs={'size': 64 }))
bgneal@609 36 interests = forms.CharField(required=False, widget=forms.TextInput(attrs={'size': 64 }))
bgneal@70 37 time_zone = forms.CharField(required=False, widget=forms.HiddenInput())
bgneal@120 38 use_24_time = forms.BooleanField(label='Show times in 24-hour mode', required=False)
bgneal@312 39 profile_text = forms.CharField(required=False,
bgneal@390 40 widget=forms.Textarea(attrs={'class': 'markItUp'}))
bgneal@312 41 signature = forms.CharField(required=False,
bgneal@390 42 widget=forms.Textarea(attrs={'class': 'markItUp'}))
bgneal@390 43 auto_favorite = forms.BooleanField(
bgneal@390 44 label='Automatically favorite every forum topic I create or reply to', required=False)
bgneal@390 45 auto_subscribe = forms.BooleanField(
bgneal@390 46 label='Automatically subscribe to every forum topic I create or reply to', required=False)
gremmie@1 47
gremmie@1 48 class Meta:
gremmie@1 49 model = UserProfile
bgneal@609 50 fields = ('location', 'country', 'birthday', 'occupation', 'interests',
bgneal@206 51 'profile_text', 'hide_email', 'signature', 'time_zone',
bgneal@390 52 'use_24_time', 'auto_favorite', 'auto_subscribe')
gremmie@1 53
bgneal@612 54 def clean_time_zone(self):
bgneal@612 55 """Ensure the timezone is valid and will work with pytz.
bgneal@1011 56
bgneal@612 57 A blank (empty) value is allowed.
bgneal@612 58 """
bgneal@612 59
bgneal@612 60 tz = self.cleaned_data['time_zone'].strip()
bgneal@612 61 if tz:
bgneal@612 62 try:
bgneal@612 63 pytz.timezone(tz)
bgneal@612 64 except pytz.UnknownTimeZoneError:
bgneal@612 65 raise forms.ValidationError('Invalid timezone')
bgneal@612 66
bgneal@612 67 return tz
bgneal@612 68
bgneal@1011 69 def _image_check(self, field_name):
bgneal@1011 70 text = self.cleaned_data[field_name]
bgneal@1011 71 if text:
bgneal@1011 72 html = site_markup(text)
bgneal@1011 73 try:
bgneal@1011 74 image_check(html)
bgneal@1011 75 except ImageCheckError as ex:
bgneal@1011 76 raise forms.ValidationError(str(ex))
bgneal@1011 77 return text
bgneal@1011 78
bgneal@1011 79 def clean_profile_text(self):
bgneal@1011 80 return self._image_check('profile_text')
bgneal@1011 81
bgneal@1011 82 def clean_signature(self):
bgneal@1011 83 return self._image_check('signature')
bgneal@1011 84
gremmie@1 85
gremmie@1 86 class UploadAvatarForm(forms.Form):
gremmie@1 87 """Form used to change a user's avatar"""
gremmie@1 88 avatar_file = forms.ImageField(required=False)
gremmie@1 89 image = None
gremmie@1 90
gremmie@1 91 def clean_avatar_file(self):
bgneal@265 92 f = self.cleaned_data['avatar_file']
bgneal@265 93 if f is not None:
bgneal@265 94 if f.size > settings.MAX_AVATAR_SIZE_BYTES:
bgneal@265 95 raise forms.ValidationError("Please upload a file smaller than "
bgneal@338 96 "%s bytes." % settings.MAX_AVATAR_SIZE_BYTES)
bgneal@265 97 try:
bgneal@265 98 self.image = parse_image(f)
bgneal@265 99 except IOError:
bgneal@265 100 raise forms.ValidationError("Please upload a valid image. "
bgneal@265 101 "The file you uploaded was either not an image or a "
bgneal@265 102 "corrupted image.")
bgneal@265 103 self.file_type = self.image.format
bgneal@265 104 return f
gremmie@1 105
bgneal@265 106 def save(self):
bgneal@265 107 """
bgneal@265 108 Perform any down-scaling needed on the new file, then return a tuple of
bgneal@265 109 (filename, file object). Note that the file object returned may not
bgneal@265 110 have a name; use the returned filename instead.
bgneal@265 111
bgneal@265 112 """
bgneal@265 113 if not self.cleaned_data['avatar_file']:
bgneal@265 114 return None, None
bgneal@265 115
bgneal@265 116 name = self.cleaned_data['avatar_file'].name
bgneal@265 117 dim = settings.MAX_AVATAR_SIZE_PIXELS
bgneal@265 118 max_size = (dim, dim)
bgneal@265 119 if self.image and self.image.size > max_size:
bgneal@265 120 self.image = downscale_image_square(self.image, dim)
bgneal@265 121
bgneal@265 122 # We need to return a Django File now. To get that from here,
bgneal@265 123 # write the image data info a StringIO and then construct a
bgneal@265 124 # Django ContentFile from that. The ContentFile has no name,
bgneal@265 125 # that is why we return one ourselves explicitly.
gremmie@1 126 s = StringIO()
bgneal@265 127 self.image.save(s, self.file_type)
bgneal@265 128 return name, ContentFile(s.getvalue())
bgneal@312 129
bgneal@265 130 return name, self.cleaned_data['avatar_file']
gremmie@1 131
bgneal@149 132
bgneal@149 133 class SearchUsersForm(forms.Form):
bgneal@149 134 """
bgneal@149 135 A form to search for users.
bgneal@149 136 """
bgneal@1078 137 username = forms.CharField(
bgneal@1078 138 max_length=30,
bgneal@1078 139 widget=forms.TextInput(attrs={
bgneal@1078 140 'class': 'sg101-autocomplete',
bgneal@1078 141 }))
bgneal@1078 142
bgneal@1078 143 def __init__(self, *args, **kwargs):
bgneal@1078 144 super(SearchUsersForm, self).__init__(*args, **kwargs)
bgneal@1078 145 url = reverse('core-ajax_users')
bgneal@1078 146 self.fields['username'].widget.attrs['data-autocomplete-url'] = url
bgneal@149 147
bgneal@149 148 def clean_username(self):
bgneal@1078 149 username = self.cleaned_data['username'].strip()
bgneal@1078 150 try:
bgneal@1078 151 User.objects.get(username=username, is_active=True)
bgneal@1078 152 except User.DoesNotExist:
bgneal@1078 153 raise forms.ValidationError("That username does not exist.")
bgneal@1078 154 return username