annotate gpp/forums/forms.py @ 429:d0f0800eef0c

Making the jquery tabbed version of the messages app the current version and removing the old. Also figured out how to dynamically update the base template's count of unread messages when messages are read.
author Brian Neal <bgneal@gmail.com>
date Tue, 03 May 2011 02:56:58 +0000
parents 26fc9ac9a0eb
children 2ff5f4c1476d
rev   line source
bgneal@83 1 """
bgneal@83 2 Forms for the forums application.
bgneal@83 3 """
bgneal@83 4 from django import forms
bgneal@95 5 from django.conf import settings
bgneal@83 6
bgneal@110 7 from forums.models import Forum
bgneal@83 8 from forums.models import Topic
bgneal@83 9 from forums.models import Post
bgneal@285 10 from forums.attachments import AttachmentProcessor
bgneal@83 11
bgneal@83 12
bgneal@106 13 class NewPostForm(forms.Form):
bgneal@86 14 """Form for creating a new post."""
bgneal@286 15 body = forms.CharField(label='',
bgneal@286 16 required=False,
bgneal@135 17 widget=forms.Textarea(attrs={'class': 'markItUp smileyTarget'}))
bgneal@89 18 topic_id = forms.IntegerField(widget=forms.HiddenInput)
bgneal@89 19 topic = None
bgneal@83 20
bgneal@89 21 class Media:
bgneal@95 22 css = {
bgneal@123 23 'all': (settings.GPP_THIRD_PARTY_CSS['markitup'] +
bgneal@123 24 settings.GPP_THIRD_PARTY_CSS['jquery-ui']),
bgneal@95 25 }
bgneal@286 26 js = (settings.GPP_THIRD_PARTY_JS['markitup'] +
bgneal@123 27 settings.GPP_THIRD_PARTY_JS['jquery-ui'] +
bgneal@123 28 ('js/forums.js', ))
bgneal@89 29
bgneal@285 30 def __init__(self, *args, **kwargs):
bgneal@285 31 super(NewPostForm, self).__init__(*args, **kwargs)
bgneal@285 32 attachments = args[0].getlist('attachment') if len(args) else []
bgneal@285 33 self.attach_proc = AttachmentProcessor(attachments)
bgneal@285 34
bgneal@286 35 def clean_body(self):
bgneal@286 36 data = self.cleaned_data['body']
bgneal@286 37 if not data and not self.attach_proc.has_attachments():
bgneal@286 38 raise forms.ValidationError("This field is required.")
bgneal@286 39 return data
bgneal@286 40
bgneal@89 41 def clean_topic_id(self):
bgneal@89 42 id = self.cleaned_data['topic_id']
bgneal@89 43 try:
bgneal@102 44 self.topic = Topic.objects.select_related().get(pk=id)
bgneal@89 45 except Topic.DoesNotExist:
bgneal@89 46 raise forms.ValidationError('invalid topic')
bgneal@286 47 return id
bgneal@89 48
bgneal@89 49 def save(self, user, ip=None):
bgneal@86 50 """
bgneal@86 51 Creates a new post from the form data and supplied arguments.
bgneal@86 52 """
bgneal@89 53 post = Post(topic=self.topic, user=user, body=self.cleaned_data['body'],
bgneal@89 54 user_ip=ip)
bgneal@86 55 post.save()
bgneal@285 56 self.attach_proc.save_attachments(post)
bgneal@89 57 return post
bgneal@83 58
bgneal@83 59
bgneal@83 60 class NewTopicForm(forms.Form):
bgneal@102 61 """
bgneal@102 62 Form for creating a new topic and 1st post to that topic.
bgneal@102 63 Superusers and moderators can also create the topic as a sticky or initially
bgneal@102 64 locked.
bgneal@102 65 """
bgneal@95 66 name = forms.CharField(label='Subject', max_length=255,
bgneal@95 67 widget=forms.TextInput(attrs={'size': 64}))
bgneal@286 68 body = forms.CharField(label='', required=False,
bgneal@135 69 widget=forms.Textarea(attrs={'class': 'markItUp smileyTarget'}))
bgneal@102 70 user = None
bgneal@102 71 forum = None
bgneal@102 72 has_mod_fields = False
bgneal@83 73
bgneal@95 74 class Media:
bgneal@95 75 css = {
bgneal@123 76 'all': (settings.GPP_THIRD_PARTY_CSS['markitup'] +
bgneal@123 77 settings.GPP_THIRD_PARTY_CSS['jquery-ui']),
bgneal@95 78 }
bgneal@286 79 js = (settings.GPP_THIRD_PARTY_JS['markitup'] +
bgneal@123 80 settings.GPP_THIRD_PARTY_JS['jquery-ui'] +
bgneal@123 81 ('js/forums.js', ))
bgneal@95 82
bgneal@102 83 def __init__(self, user, forum, *args, **kwargs):
bgneal@102 84 super(NewTopicForm, self).__init__(*args, **kwargs)
bgneal@102 85 self.user = user
bgneal@102 86 self.forum = forum
bgneal@102 87
bgneal@102 88 if user.is_superuser or user in forum.moderators.all():
bgneal@102 89 self.fields['sticky'] = forms.BooleanField(required=False)
bgneal@102 90 self.fields['locked'] = forms.BooleanField(required=False)
bgneal@102 91 self.has_mod_fields = True
bgneal@102 92
bgneal@285 93 attachments = args[0].getlist('attachment') if len(args) else []
bgneal@285 94 self.attach_proc = AttachmentProcessor(attachments)
bgneal@285 95
bgneal@286 96 # If this form is being POSTed, and the user is trying to add
bgneal@286 97 # attachments, create hidden fields to list the Oembed ids. In
bgneal@286 98 # case the form isn't valid, the client-side javascript will know
bgneal@286 99 # which Oembed media to ask for when the form is displayed with
bgneal@286 100 # errors.
bgneal@286 101 if self.attach_proc.has_attachments():
bgneal@286 102 pks = self.attach_proc.get_ids()
bgneal@286 103 self.fields['attachment'] = forms.MultipleChoiceField(label='',
bgneal@286 104 widget=forms.MultipleHiddenInput(),
bgneal@286 105 choices=[(v, v) for v in pks])
bgneal@286 106
bgneal@286 107 def clean_body(self):
bgneal@286 108 data = self.cleaned_data['body']
bgneal@286 109 if not data and not self.attach_proc.has_attachments():
bgneal@286 110 raise forms.ValidationError("This field is required.")
bgneal@286 111 return data
bgneal@286 112
bgneal@102 113 def save(self, ip=None):
bgneal@83 114 """
bgneal@83 115 Creates the new Topic and first Post from the form data and supplied
bgneal@86 116 arguments.
bgneal@83 117 """
bgneal@102 118 topic = Topic(forum=self.forum,
bgneal@83 119 name=self.cleaned_data['name'],
bgneal@102 120 user=self.user,
bgneal@102 121 sticky=self.has_mod_fields and self.cleaned_data['sticky'],
bgneal@102 122 locked=self.has_mod_fields and self.cleaned_data['locked'])
bgneal@83 123 topic.save()
bgneal@83 124
bgneal@83 125 post = Post(topic=topic,
bgneal@102 126 user=self.user,
bgneal@83 127 body=self.cleaned_data['body'],
bgneal@83 128 user_ip=ip)
bgneal@83 129 post.save()
bgneal@285 130
bgneal@285 131 self.attach_proc.save_attachments(post)
bgneal@285 132
bgneal@83 133 return topic
bgneal@106 134
bgneal@106 135
bgneal@106 136 class PostForm(forms.ModelForm):
bgneal@106 137 """
bgneal@108 138 Form for editing an existing post or a new, non-quick post.
bgneal@106 139 """
bgneal@286 140 body = forms.CharField(label='',
bgneal@286 141 required=False,
bgneal@135 142 widget=forms.Textarea(attrs={'class': 'markItUp smileyTarget'}))
bgneal@106 143
bgneal@106 144 class Meta:
bgneal@106 145 model = Post
bgneal@106 146 fields = ('body', )
bgneal@106 147
bgneal@106 148 class Media:
bgneal@106 149 css = {
bgneal@123 150 'all': (settings.GPP_THIRD_PARTY_CSS['markitup'] +
bgneal@123 151 settings.GPP_THIRD_PARTY_CSS['jquery-ui']),
bgneal@106 152 }
bgneal@286 153 js = (settings.GPP_THIRD_PARTY_JS['markitup'] +
bgneal@123 154 settings.GPP_THIRD_PARTY_JS['jquery-ui'] +
bgneal@123 155 ('js/forums.js', ))
bgneal@110 156
bgneal@286 157 def __init__(self, *args, **kwargs):
bgneal@295 158 topic_name = kwargs.pop('topic_name', None)
bgneal@286 159 super(PostForm, self).__init__(*args, **kwargs)
bgneal@286 160
bgneal@295 161 if topic_name is not None: # this is a "first post"
bgneal@295 162 self.fields.insert(0, 'name', forms.CharField(label='Subject',
bgneal@295 163 max_length=255,
bgneal@295 164 widget=forms.TextInput(attrs={'size': 64})))
bgneal@295 165 self.initial['name'] = topic_name
bgneal@295 166
bgneal@286 167 attachments = args[0].getlist('attachment') if len(args) else []
bgneal@286 168 self.attach_proc = AttachmentProcessor(attachments)
bgneal@295 169
bgneal@286 170 # If this form is being used to edit an existing post, and that post
bgneal@286 171 # has attachments, create a hidden post_id field. The client-side
bgneal@286 172 # AJAX will use this as a cue to retrieve the HTML for the embedded
bgneal@286 173 # media.
bgneal@286 174 if 'instance' in kwargs:
bgneal@286 175 post = kwargs['instance']
bgneal@286 176 if post.attachments.count():
bgneal@286 177 self.fields['post_id'] = forms.CharField(label='',
bgneal@286 178 widget=forms.HiddenInput(attrs={'value': post.id}))
bgneal@286 179
bgneal@286 180 def clean_body(self):
bgneal@286 181 data = self.cleaned_data['body']
bgneal@286 182 if not data and not self.attach_proc.has_attachments():
bgneal@286 183 raise forms.ValidationError('This field is required.')
bgneal@286 184 return data
bgneal@286 185
bgneal@295 186 def save(self, *args, **kwargs):
bgneal@295 187 commit = kwargs.get('commit', False)
bgneal@295 188 post = super(PostForm, self).save(*args, **kwargs)
bgneal@295 189
bgneal@295 190 # Are we saving a "first post"?
bgneal@295 191 if 'name' in self.cleaned_data:
bgneal@295 192 post.topic.name = self.cleaned_data['name']
bgneal@295 193 if commit:
bgneal@295 194 post.topic.save()
bgneal@295 195 return post
bgneal@295 196
bgneal@110 197
bgneal@110 198 class MoveTopicForm(forms.Form):
bgneal@111 199 """
bgneal@111 200 Form for a moderator to move a topic to a forum.
bgneal@111 201 """
bgneal@286 202 forums = forms.ModelChoiceField(label='Move to forum',
bgneal@111 203 queryset=Forum.objects.none())
bgneal@110 204
bgneal@111 205 def __init__(self, user, *args, **kwargs):
bgneal@286 206 hide_label = kwargs.pop('hide_label', False)
bgneal@111 207 required = kwargs.pop('required', True)
bgneal@111 208 super(MoveTopicForm, self).__init__(*args, **kwargs)
bgneal@111 209 self.fields['forums'].queryset = \
bgneal@111 210 Forum.objects.forums_for_user(user).order_by('name')
bgneal@111 211 if hide_label:
bgneal@111 212 self.fields['forums'].label = ''
bgneal@111 213 self.fields['forums'].required = required
bgneal@110 214
bgneal@115 215
bgneal@115 216 class SplitTopicForm(forms.Form):
bgneal@115 217 """
bgneal@115 218 Form for a moderator to split posts from a topic to a new topic.
bgneal@115 219 """
bgneal@115 220 name = forms.CharField(label='New topic title', max_length=255,
bgneal@115 221 widget=forms.TextInput(attrs={'size': 64}))
bgneal@286 222 forums = forms.ModelChoiceField(label='Forum for new topic',
bgneal@115 223 queryset=Forum.objects.none())
bgneal@115 224 post_ids = []
bgneal@115 225 split_at = False
bgneal@115 226
bgneal@115 227 def __init__(self, user, *args, **kwargs):
bgneal@115 228 super(SplitTopicForm, self).__init__(*args, **kwargs)
bgneal@115 229 self.fields['forums'].queryset = \
bgneal@115 230 Forum.objects.forums_for_user(user).order_by('name')
bgneal@115 231
bgneal@115 232 def clean(self):
bgneal@115 233 self.post_ids = self.data.getlist('post_ids')
bgneal@115 234 if len(self.post_ids) == 0:
bgneal@115 235 raise forms.ValidationError('Please select some posts')
bgneal@115 236
bgneal@115 237 self.split_at = 'split-at' in self.data
bgneal@115 238 if self.split_at and len(self.post_ids) > 1:
bgneal@115 239 raise forms.ValidationError('Please select only one post to split the topic at')
bgneal@115 240
bgneal@115 241 return self.cleaned_data