diff options
-rw-r--r-- | askbot/forms.py | 17 | ||||
-rw-r--r-- | askbot/migrations/0131_auto__add_draftquestion__add_draftanswer.py | 356 | ||||
-rw-r--r-- | askbot/models/__init__.py | 4 | ||||
-rw-r--r-- | askbot/models/post.py | 14 | ||||
-rw-r--r-- | askbot/models/question.py | 13 | ||||
-rw-r--r-- | askbot/skins/common/media/js/post.js | 136 | ||||
-rw-r--r-- | askbot/skins/common/media/js/utils.js | 14 | ||||
-rw-r--r-- | askbot/skins/default/templates/ask.html | 12 | ||||
-rw-r--r-- | askbot/skins/default/templates/meta/html_head_javascript.html | 1 | ||||
-rw-r--r-- | askbot/skins/default/templates/question.html | 2 | ||||
-rw-r--r-- | askbot/skins/default/templates/question/javascript.html | 7 | ||||
-rw-r--r-- | askbot/skins/default/templates/widgets/ask_form.html | 1 | ||||
-rw-r--r-- | askbot/urls.py | 10 | ||||
-rw-r--r-- | askbot/views/commands.py | 60 | ||||
-rw-r--r-- | askbot/views/writers.py | 22 |
15 files changed, 660 insertions, 9 deletions
diff --git a/askbot/forms.py b/askbot/forms.py index 9fc66f45..fe65cd02 100644 --- a/askbot/forms.py +++ b/askbot/forms.py @@ -218,7 +218,7 @@ class TitleField(forms.CharField): """Fild receiving question title""" def __init__(self, *args, **kwargs): super(TitleField, self).__init__(*args, **kwargs) - self.required = True + self.required = kwargs.get('required', True) self.widget = forms.TextInput( attrs={'size': 70, 'autocomplete': 'off'} ) @@ -271,7 +271,7 @@ class EditorField(forms.CharField): def __init__(self, *args, **kwargs): super(EditorField, self).__init__(*args, **kwargs) - self.required = True + self.required = kwargs.get('required', True) self.widget = forms.Textarea(attrs={'id': 'editor'}) self.label = _('content') self.help_text = u'' @@ -756,6 +756,19 @@ class PostPrivatelyForm(forms.Form, FormWithHideableFields): return self.cleaned_data['post_privately'] +class DraftQuestionForm(forms.Form): + """No real validation required for this form""" + title = forms.CharField(required=False) + text = forms.CharField(required=False) + tagnames = forms.CharField(required=False) + + +class DraftAnswerForm(forms.Form): + """Only thread_id is required""" + thread_id = forms.IntegerField() + text = forms.CharField(required=False) + + class AskForm(PostPrivatelyForm): """the form used to askbot questions field ask_anonymously is shown to the user if the diff --git a/askbot/migrations/0131_auto__add_draftquestion__add_draftanswer.py b/askbot/migrations/0131_auto__add_draftquestion__add_draftanswer.py new file mode 100644 index 00000000..bceca754 --- /dev/null +++ b/askbot/migrations/0131_auto__add_draftquestion__add_draftanswer.py @@ -0,0 +1,356 @@ +# -*- coding: utf-8 -*- +import datetime +from south.db import db +from south.v2 import SchemaMigration +from django.db import models + + +class Migration(SchemaMigration): + + def forwards(self, orm): + # Adding model 'DraftQuestion' + db.create_table('askbot_draftquestion', ( + ('id', self.gf('django.db.models.fields.AutoField')(primary_key=True)), + ('author', self.gf('django.db.models.fields.related.ForeignKey')(to=orm['auth.User'])), + ('title', self.gf('django.db.models.fields.CharField')(max_length=300, null=True)), + ('text', self.gf('django.db.models.fields.TextField')(null=True)), + ('tagnames', self.gf('django.db.models.fields.CharField')(max_length=125, null=True)), + )) + db.send_create_signal('askbot', ['DraftQuestion']) + + # Adding model 'DraftAnswer' + db.create_table('askbot_draftanswer', ( + ('id', self.gf('django.db.models.fields.AutoField')(primary_key=True)), + ('thread', self.gf('django.db.models.fields.related.ForeignKey')(related_name='draft_answers', to=orm['askbot.Thread'])), + ('author', self.gf('django.db.models.fields.related.ForeignKey')(related_name='draft_answers', to=orm['auth.User'])), + ('text', self.gf('django.db.models.fields.TextField')(null=True)), + )) + db.send_create_signal('askbot', ['DraftAnswer']) + + def backwards(self, orm): + # Deleting model 'DraftQuestion' + db.delete_table('askbot_draftquestion') + + # Deleting model 'DraftAnswer' + db.delete_table('askbot_draftanswer') + + models = { + 'askbot.activity': { + 'Meta': {'object_name': 'Activity', 'db_table': "u'activity'"}, + 'active_at': ('django.db.models.fields.DateTimeField', [], {'default': 'datetime.datetime.now'}), + 'activity_type': ('django.db.models.fields.SmallIntegerField', [], {}), + 'content_type': ('django.db.models.fields.related.ForeignKey', [], {'to': "orm['contenttypes.ContentType']"}), + 'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}), + 'is_auditted': ('django.db.models.fields.BooleanField', [], {'default': 'False'}), + 'object_id': ('django.db.models.fields.PositiveIntegerField', [], {}), + 'question': ('django.db.models.fields.related.ForeignKey', [], {'to': "orm['askbot.Post']", 'null': 'True'}), + 'receiving_users': ('django.db.models.fields.related.ManyToManyField', [], {'related_name': "'received_activity'", 'symmetrical': 'False', 'to': "orm['auth.User']"}), + 'recipients': ('django.db.models.fields.related.ManyToManyField', [], {'related_name': "'incoming_activity'", 'symmetrical': 'False', 'through': "orm['askbot.ActivityAuditStatus']", 'to': "orm['auth.User']"}), + 'summary': ('django.db.models.fields.TextField', [], {'default': "''"}), + 'user': ('django.db.models.fields.related.ForeignKey', [], {'to': "orm['auth.User']"}) + }, + 'askbot.activityauditstatus': { + 'Meta': {'unique_together': "(('user', 'activity'),)", 'object_name': 'ActivityAuditStatus'}, + 'activity': ('django.db.models.fields.related.ForeignKey', [], {'to': "orm['askbot.Activity']"}), + 'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}), + 'status': ('django.db.models.fields.SmallIntegerField', [], {'default': '0'}), + 'user': ('django.db.models.fields.related.ForeignKey', [], {'to': "orm['auth.User']"}) + }, + 'askbot.anonymousanswer': { + 'Meta': {'object_name': 'AnonymousAnswer'}, + 'added_at': ('django.db.models.fields.DateTimeField', [], {'default': 'datetime.datetime.now'}), + 'author': ('django.db.models.fields.related.ForeignKey', [], {'to': "orm['auth.User']", 'null': 'True'}), + 'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}), + 'ip_addr': ('django.db.models.fields.IPAddressField', [], {'max_length': '15'}), + 'question': ('django.db.models.fields.related.ForeignKey', [], {'related_name': "'anonymous_answers'", 'to': "orm['askbot.Post']"}), + 'session_key': ('django.db.models.fields.CharField', [], {'max_length': '40'}), + 'summary': ('django.db.models.fields.CharField', [], {'max_length': '180'}), + 'text': ('django.db.models.fields.TextField', [], {}), + 'wiki': ('django.db.models.fields.BooleanField', [], {'default': 'False'}) + }, + 'askbot.anonymousquestion': { + 'Meta': {'object_name': 'AnonymousQuestion'}, + 'added_at': ('django.db.models.fields.DateTimeField', [], {'default': 'datetime.datetime.now'}), + 'author': ('django.db.models.fields.related.ForeignKey', [], {'to': "orm['auth.User']", 'null': 'True'}), + 'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}), + 'ip_addr': ('django.db.models.fields.IPAddressField', [], {'max_length': '15'}), + 'is_anonymous': ('django.db.models.fields.BooleanField', [], {'default': 'False'}), + 'session_key': ('django.db.models.fields.CharField', [], {'max_length': '40'}), + 'summary': ('django.db.models.fields.CharField', [], {'max_length': '180'}), + 'tagnames': ('django.db.models.fields.CharField', [], {'max_length': '125'}), + 'text': ('django.db.models.fields.TextField', [], {}), + 'title': ('django.db.models.fields.CharField', [], {'max_length': '300'}), + 'wiki': ('django.db.models.fields.BooleanField', [], {'default': 'False'}) + }, + 'askbot.award': { + 'Meta': {'object_name': 'Award', 'db_table': "u'award'"}, + 'awarded_at': ('django.db.models.fields.DateTimeField', [], {'default': 'datetime.datetime.now'}), + 'badge': ('django.db.models.fields.related.ForeignKey', [], {'related_name': "'award_badge'", 'to': "orm['askbot.BadgeData']"}), + 'content_type': ('django.db.models.fields.related.ForeignKey', [], {'to': "orm['contenttypes.ContentType']"}), + 'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}), + 'notified': ('django.db.models.fields.BooleanField', [], {'default': 'False'}), + 'object_id': ('django.db.models.fields.PositiveIntegerField', [], {}), + 'user': ('django.db.models.fields.related.ForeignKey', [], {'related_name': "'award_user'", 'to': "orm['auth.User']"}) + }, + 'askbot.badgedata': { + 'Meta': {'ordering': "('slug',)", 'object_name': 'BadgeData'}, + 'awarded_count': ('django.db.models.fields.PositiveIntegerField', [], {'default': '0'}), + 'awarded_to': ('django.db.models.fields.related.ManyToManyField', [], {'related_name': "'badges'", 'symmetrical': 'False', 'through': "orm['askbot.Award']", 'to': "orm['auth.User']"}), + 'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}), + 'slug': ('django.db.models.fields.SlugField', [], {'unique': 'True', 'max_length': '50'}) + }, + 'askbot.draftanswer': { + 'Meta': {'object_name': 'DraftAnswer'}, + 'author': ('django.db.models.fields.related.ForeignKey', [], {'related_name': "'draft_answers'", 'to': "orm['auth.User']"}), + 'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}), + 'text': ('django.db.models.fields.TextField', [], {'null': 'True'}), + 'thread': ('django.db.models.fields.related.ForeignKey', [], {'related_name': "'draft_answers'", 'to': "orm['askbot.Thread']"}) + }, + 'askbot.draftquestion': { + 'Meta': {'object_name': 'DraftQuestion'}, + 'author': ('django.db.models.fields.related.ForeignKey', [], {'to': "orm['auth.User']"}), + 'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}), + 'tagnames': ('django.db.models.fields.CharField', [], {'max_length': '125', 'null': 'True'}), + 'text': ('django.db.models.fields.TextField', [], {'null': 'True'}), + 'title': ('django.db.models.fields.CharField', [], {'max_length': '300', 'null': 'True'}) + }, + 'askbot.emailfeedsetting': { + 'Meta': {'unique_together': "(('subscriber', 'feed_type'),)", 'object_name': 'EmailFeedSetting'}, + 'added_at': ('django.db.models.fields.DateTimeField', [], {'auto_now_add': 'True', 'blank': 'True'}), + 'feed_type': ('django.db.models.fields.CharField', [], {'max_length': '16'}), + 'frequency': ('django.db.models.fields.CharField', [], {'default': "'n'", 'max_length': '8'}), + 'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}), + 'reported_at': ('django.db.models.fields.DateTimeField', [], {'null': 'True'}), + 'subscriber': ('django.db.models.fields.related.ForeignKey', [], {'related_name': "'notification_subscriptions'", 'to': "orm['auth.User']"}) + }, + 'askbot.favoritequestion': { + 'Meta': {'object_name': 'FavoriteQuestion', 'db_table': "u'favorite_question'"}, + 'added_at': ('django.db.models.fields.DateTimeField', [], {'default': 'datetime.datetime.now'}), + 'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}), + 'thread': ('django.db.models.fields.related.ForeignKey', [], {'to': "orm['askbot.Thread']"}), + 'user': ('django.db.models.fields.related.ForeignKey', [], {'related_name': "'user_favorite_questions'", 'to': "orm['auth.User']"}) + }, + 'askbot.groupmembership': { + 'Meta': {'unique_together': "(('group', 'user'),)", 'object_name': 'GroupMembership'}, + 'group': ('django.db.models.fields.related.ForeignKey', [], {'related_name': "'user_memberships'", 'to': "orm['askbot.Tag']"}), + 'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}), + 'user': ('django.db.models.fields.related.ForeignKey', [], {'related_name': "'group_memberships'", 'to': "orm['auth.User']"}) + }, + 'askbot.groupprofile': { + 'Meta': {'object_name': 'GroupProfile'}, + 'group_tag': ('django.db.models.fields.related.OneToOneField', [], {'related_name': "'group_profile'", 'unique': 'True', 'to': "orm['askbot.Tag']"}), + 'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}), + 'is_open': ('django.db.models.fields.BooleanField', [], {'default': 'False'}), + 'logo_url': ('django.db.models.fields.URLField', [], {'max_length': '200', 'null': 'True'}), + 'moderate_email': ('django.db.models.fields.BooleanField', [], {'default': 'True'}), + 'preapproved_email_domains': ('django.db.models.fields.TextField', [], {'default': "''", 'null': 'True', 'blank': 'True'}), + 'preapproved_emails': ('django.db.models.fields.TextField', [], {'default': "''", 'null': 'True', 'blank': 'True'}) + }, + 'askbot.markedtag': { + 'Meta': {'object_name': 'MarkedTag'}, + 'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}), + 'reason': ('django.db.models.fields.CharField', [], {'max_length': '16'}), + 'tag': ('django.db.models.fields.related.ForeignKey', [], {'related_name': "'user_selections'", 'to': "orm['askbot.Tag']"}), + 'user': ('django.db.models.fields.related.ForeignKey', [], {'related_name': "'tag_selections'", 'to': "orm['auth.User']"}) + }, + 'askbot.post': { + 'Meta': {'object_name': 'Post'}, + 'added_at': ('django.db.models.fields.DateTimeField', [], {'default': 'datetime.datetime.now'}), + 'approved': ('django.db.models.fields.BooleanField', [], {'default': 'True', 'db_index': 'True'}), + 'author': ('django.db.models.fields.related.ForeignKey', [], {'related_name': "'posts'", 'to': "orm['auth.User']"}), + 'comment_count': ('django.db.models.fields.PositiveIntegerField', [], {'default': '0'}), + 'deleted': ('django.db.models.fields.BooleanField', [], {'default': 'False', 'db_index': 'True'}), + 'deleted_at': ('django.db.models.fields.DateTimeField', [], {'null': 'True', 'blank': 'True'}), + 'deleted_by': ('django.db.models.fields.related.ForeignKey', [], {'blank': 'True', 'related_name': "'deleted_posts'", 'null': 'True', 'to': "orm['auth.User']"}), + 'groups': ('django.db.models.fields.related.ManyToManyField', [], {'related_name': "'group_posts'", 'symmetrical': 'False', 'to': "orm['askbot.Tag']"}), + 'html': ('django.db.models.fields.TextField', [], {'null': 'True'}), + 'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}), + 'is_anonymous': ('django.db.models.fields.BooleanField', [], {'default': 'False'}), + 'last_edited_at': ('django.db.models.fields.DateTimeField', [], {'null': 'True', 'blank': 'True'}), + 'last_edited_by': ('django.db.models.fields.related.ForeignKey', [], {'blank': 'True', 'related_name': "'last_edited_posts'", 'null': 'True', 'to': "orm['auth.User']"}), + 'locked': ('django.db.models.fields.BooleanField', [], {'default': 'False'}), + 'locked_at': ('django.db.models.fields.DateTimeField', [], {'null': 'True', 'blank': 'True'}), + 'locked_by': ('django.db.models.fields.related.ForeignKey', [], {'blank': 'True', 'related_name': "'locked_posts'", 'null': 'True', 'to': "orm['auth.User']"}), + 'offensive_flag_count': ('django.db.models.fields.SmallIntegerField', [], {'default': '0'}), + 'old_answer_id': ('django.db.models.fields.PositiveIntegerField', [], {'default': 'None', 'unique': 'True', 'null': 'True', 'blank': 'True'}), + 'old_comment_id': ('django.db.models.fields.PositiveIntegerField', [], {'default': 'None', 'unique': 'True', 'null': 'True', 'blank': 'True'}), + 'old_question_id': ('django.db.models.fields.PositiveIntegerField', [], {'default': 'None', 'unique': 'True', 'null': 'True', 'blank': 'True'}), + 'parent': ('django.db.models.fields.related.ForeignKey', [], {'blank': 'True', 'related_name': "'comments'", 'null': 'True', 'to': "orm['askbot.Post']"}), + 'post_type': ('django.db.models.fields.CharField', [], {'max_length': '255', 'db_index': 'True'}), + 'score': ('django.db.models.fields.IntegerField', [], {'default': '0'}), + 'summary': ('django.db.models.fields.CharField', [], {'max_length': '180'}), + 'text': ('django.db.models.fields.TextField', [], {'null': 'True'}), + 'thread': ('django.db.models.fields.related.ForeignKey', [], {'default': 'None', 'related_name': "'posts'", 'null': 'True', 'blank': 'True', 'to': "orm['askbot.Thread']"}), + 'vote_down_count': ('django.db.models.fields.IntegerField', [], {'default': '0'}), + 'vote_up_count': ('django.db.models.fields.IntegerField', [], {'default': '0'}), + 'wiki': ('django.db.models.fields.BooleanField', [], {'default': 'False'}), + 'wikified_at': ('django.db.models.fields.DateTimeField', [], {'null': 'True', 'blank': 'True'}) + }, + 'askbot.postflagreason': { + 'Meta': {'object_name': 'PostFlagReason'}, + 'added_at': ('django.db.models.fields.DateTimeField', [], {}), + 'author': ('django.db.models.fields.related.ForeignKey', [], {'to': "orm['auth.User']"}), + 'details': ('django.db.models.fields.related.ForeignKey', [], {'related_name': "'post_reject_reasons'", 'to': "orm['askbot.Post']"}), + 'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}), + 'title': ('django.db.models.fields.CharField', [], {'max_length': '128'}) + }, + 'askbot.postrevision': { + 'Meta': {'ordering': "('-revision',)", 'unique_together': "(('post', 'revision'),)", 'object_name': 'PostRevision'}, + 'approved': ('django.db.models.fields.BooleanField', [], {'default': 'False', 'db_index': 'True'}), + 'approved_at': ('django.db.models.fields.DateTimeField', [], {'null': 'True', 'blank': 'True'}), + 'approved_by': ('django.db.models.fields.related.ForeignKey', [], {'to': "orm['auth.User']", 'null': 'True', 'blank': 'True'}), + 'author': ('django.db.models.fields.related.ForeignKey', [], {'related_name': "'postrevisions'", 'to': "orm['auth.User']"}), + 'by_email': ('django.db.models.fields.BooleanField', [], {'default': 'False'}), + 'email_address': ('django.db.models.fields.EmailField', [], {'max_length': '75', 'null': 'True', 'blank': 'True'}), + 'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}), + 'is_anonymous': ('django.db.models.fields.BooleanField', [], {'default': 'False'}), + 'post': ('django.db.models.fields.related.ForeignKey', [], {'blank': 'True', 'related_name': "'revisions'", 'null': 'True', 'to': "orm['askbot.Post']"}), + 'revised_at': ('django.db.models.fields.DateTimeField', [], {}), + 'revision': ('django.db.models.fields.PositiveIntegerField', [], {}), + 'summary': ('django.db.models.fields.CharField', [], {'max_length': '300', 'blank': 'True'}), + 'tagnames': ('django.db.models.fields.CharField', [], {'default': "''", 'max_length': '125', 'blank': 'True'}), + 'text': ('django.db.models.fields.TextField', [], {}), + 'title': ('django.db.models.fields.CharField', [], {'default': "''", 'max_length': '300', 'blank': 'True'}) + }, + 'askbot.questionview': { + 'Meta': {'object_name': 'QuestionView'}, + 'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}), + 'question': ('django.db.models.fields.related.ForeignKey', [], {'related_name': "'viewed'", 'to': "orm['askbot.Post']"}), + 'when': ('django.db.models.fields.DateTimeField', [], {}), + 'who': ('django.db.models.fields.related.ForeignKey', [], {'related_name': "'question_views'", 'to': "orm['auth.User']"}) + }, + 'askbot.replyaddress': { + 'Meta': {'object_name': 'ReplyAddress'}, + 'address': ('django.db.models.fields.CharField', [], {'unique': 'True', 'max_length': '25'}), + 'allowed_from_email': ('django.db.models.fields.EmailField', [], {'max_length': '150'}), + 'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}), + 'post': ('django.db.models.fields.related.ForeignKey', [], {'related_name': "'reply_addresses'", 'null': 'True', 'to': "orm['askbot.Post']"}), + 'reply_action': ('django.db.models.fields.CharField', [], {'default': "'auto_answer_or_comment'", 'max_length': '32'}), + 'response_post': ('django.db.models.fields.related.ForeignKey', [], {'related_name': "'edit_addresses'", 'null': 'True', 'to': "orm['askbot.Post']"}), + 'used_at': ('django.db.models.fields.DateTimeField', [], {'default': 'None', 'null': 'True'}), + 'user': ('django.db.models.fields.related.ForeignKey', [], {'to': "orm['auth.User']"}) + }, + 'askbot.repute': { + 'Meta': {'object_name': 'Repute', 'db_table': "u'repute'"}, + 'comment': ('django.db.models.fields.CharField', [], {'max_length': '128', 'null': 'True'}), + 'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}), + 'negative': ('django.db.models.fields.SmallIntegerField', [], {'default': '0'}), + 'positive': ('django.db.models.fields.SmallIntegerField', [], {'default': '0'}), + 'question': ('django.db.models.fields.related.ForeignKey', [], {'to': "orm['askbot.Post']", 'null': 'True', 'blank': 'True'}), + 'reputation': ('django.db.models.fields.IntegerField', [], {'default': '1'}), + 'reputation_type': ('django.db.models.fields.SmallIntegerField', [], {}), + 'reputed_at': ('django.db.models.fields.DateTimeField', [], {'default': 'datetime.datetime.now'}), + 'user': ('django.db.models.fields.related.ForeignKey', [], {'to': "orm['auth.User']"}) + }, + 'askbot.tag': { + 'Meta': {'ordering': "('-used_count', 'name')", 'object_name': 'Tag', 'db_table': "u'tag'"}, + 'created_by': ('django.db.models.fields.related.ForeignKey', [], {'related_name': "'created_tags'", 'to': "orm['auth.User']"}), + 'deleted': ('django.db.models.fields.BooleanField', [], {'default': 'False'}), + 'deleted_at': ('django.db.models.fields.DateTimeField', [], {'null': 'True', 'blank': 'True'}), + 'deleted_by': ('django.db.models.fields.related.ForeignKey', [], {'blank': 'True', 'related_name': "'deleted_tags'", 'null': 'True', 'to': "orm['auth.User']"}), + 'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}), + 'name': ('django.db.models.fields.CharField', [], {'unique': 'True', 'max_length': '255'}), + 'status': ('django.db.models.fields.SmallIntegerField', [], {'default': '1'}), + 'suggested_by': ('django.db.models.fields.related.ManyToManyField', [], {'related_name': "'suggested_tags'", 'symmetrical': 'False', 'to': "orm['auth.User']"}), + 'tag_wiki': ('django.db.models.fields.related.OneToOneField', [], {'related_name': "'described_tag'", 'unique': 'True', 'null': 'True', 'to': "orm['askbot.Post']"}), + 'used_count': ('django.db.models.fields.PositiveIntegerField', [], {'default': '0'}) + }, + 'askbot.thread': { + 'Meta': {'object_name': 'Thread'}, + 'accepted_answer': ('django.db.models.fields.related.ForeignKey', [], {'blank': 'True', 'related_name': "'+'", 'null': 'True', 'to': "orm['askbot.Post']"}), + 'added_at': ('django.db.models.fields.DateTimeField', [], {'default': 'datetime.datetime.now'}), + 'answer_accepted_at': ('django.db.models.fields.DateTimeField', [], {'null': 'True', 'blank': 'True'}), + 'answer_count': ('django.db.models.fields.PositiveIntegerField', [], {'default': '0'}), + 'approved': ('django.db.models.fields.BooleanField', [], {'default': 'True', 'db_index': 'True'}), + 'close_reason': ('django.db.models.fields.SmallIntegerField', [], {'null': 'True', 'blank': 'True'}), + 'closed': ('django.db.models.fields.BooleanField', [], {'default': 'False'}), + 'closed_at': ('django.db.models.fields.DateTimeField', [], {'null': 'True', 'blank': 'True'}), + 'closed_by': ('django.db.models.fields.related.ForeignKey', [], {'to': "orm['auth.User']", 'null': 'True', 'blank': 'True'}), + 'favorited_by': ('django.db.models.fields.related.ManyToManyField', [], {'related_name': "'unused_favorite_threads'", 'symmetrical': 'False', 'through': "orm['askbot.FavoriteQuestion']", 'to': "orm['auth.User']"}), + 'favourite_count': ('django.db.models.fields.PositiveIntegerField', [], {'default': '0'}), + 'followed_by': ('django.db.models.fields.related.ManyToManyField', [], {'related_name': "'followed_threads'", 'symmetrical': 'False', 'to': "orm['auth.User']"}), + 'groups': ('django.db.models.fields.related.ManyToManyField', [], {'related_name': "'group_threads'", 'symmetrical': 'False', 'to': "orm['askbot.Tag']"}), + 'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}), + 'last_activity_at': ('django.db.models.fields.DateTimeField', [], {'default': 'datetime.datetime.now'}), + 'last_activity_by': ('django.db.models.fields.related.ForeignKey', [], {'related_name': "'unused_last_active_in_threads'", 'to': "orm['auth.User']"}), + 'score': ('django.db.models.fields.IntegerField', [], {'default': '0'}), + 'tagnames': ('django.db.models.fields.CharField', [], {'max_length': '125'}), + 'tags': ('django.db.models.fields.related.ManyToManyField', [], {'related_name': "'threads'", 'symmetrical': 'False', 'to': "orm['askbot.Tag']"}), + 'title': ('django.db.models.fields.CharField', [], {'max_length': '300'}), + 'view_count': ('django.db.models.fields.PositiveIntegerField', [], {'default': '0'}) + }, + 'askbot.vote': { + 'Meta': {'unique_together': "(('user', 'voted_post'),)", 'object_name': 'Vote', 'db_table': "u'vote'"}, + 'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}), + 'user': ('django.db.models.fields.related.ForeignKey', [], {'related_name': "'votes'", 'to': "orm['auth.User']"}), + 'vote': ('django.db.models.fields.SmallIntegerField', [], {}), + 'voted_at': ('django.db.models.fields.DateTimeField', [], {'default': 'datetime.datetime.now'}), + 'voted_post': ('django.db.models.fields.related.ForeignKey', [], {'related_name': "'votes'", 'to': "orm['askbot.Post']"}) + }, + 'auth.group': { + 'Meta': {'object_name': 'Group'}, + 'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}), + 'name': ('django.db.models.fields.CharField', [], {'unique': 'True', 'max_length': '80'}), + 'permissions': ('django.db.models.fields.related.ManyToManyField', [], {'to': "orm['auth.Permission']", 'symmetrical': 'False', 'blank': 'True'}) + }, + 'auth.permission': { + 'Meta': {'ordering': "('content_type__app_label', 'content_type__model', 'codename')", 'unique_together': "(('content_type', 'codename'),)", 'object_name': 'Permission'}, + 'codename': ('django.db.models.fields.CharField', [], {'max_length': '100'}), + 'content_type': ('django.db.models.fields.related.ForeignKey', [], {'to': "orm['contenttypes.ContentType']"}), + 'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}), + 'name': ('django.db.models.fields.CharField', [], {'max_length': '50'}) + }, + 'auth.user': { + 'Meta': {'object_name': 'User'}, + 'about': ('django.db.models.fields.TextField', [], {'blank': 'True'}), + 'avatar_type': ('django.db.models.fields.CharField', [], {'default': "'n'", 'max_length': '1'}), + 'bronze': ('django.db.models.fields.SmallIntegerField', [], {'default': '0'}), + 'consecutive_days_visit_count': ('django.db.models.fields.IntegerField', [], {'default': '0'}), + 'country': ('django_countries.fields.CountryField', [], {'max_length': '2', 'blank': 'True'}), + 'date_joined': ('django.db.models.fields.DateTimeField', [], {'default': 'datetime.datetime.now'}), + 'date_of_birth': ('django.db.models.fields.DateField', [], {'null': 'True', 'blank': 'True'}), + 'display_tag_filter_strategy': ('django.db.models.fields.SmallIntegerField', [], {'default': '0'}), + 'email': ('django.db.models.fields.EmailField', [], {'max_length': '75', 'blank': 'True'}), + 'email_isvalid': ('django.db.models.fields.BooleanField', [], {'default': 'False'}), + 'email_key': ('django.db.models.fields.CharField', [], {'max_length': '32', 'null': 'True'}), + 'email_signature': ('django.db.models.fields.TextField', [], {'blank': 'True'}), + 'email_tag_filter_strategy': ('django.db.models.fields.SmallIntegerField', [], {'default': '1'}), + 'first_name': ('django.db.models.fields.CharField', [], {'max_length': '30', 'blank': 'True'}), + 'gold': ('django.db.models.fields.SmallIntegerField', [], {'default': '0'}), + 'gravatar': ('django.db.models.fields.CharField', [], {'max_length': '32'}), + 'groups': ('django.db.models.fields.related.ManyToManyField', [], {'to': "orm['auth.Group']", 'symmetrical': 'False', 'blank': 'True'}), + 'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}), + 'ignored_tags': ('django.db.models.fields.TextField', [], {'blank': 'True'}), + 'interesting_tags': ('django.db.models.fields.TextField', [], {'blank': 'True'}), + 'is_active': ('django.db.models.fields.BooleanField', [], {'default': 'True'}), + 'is_staff': ('django.db.models.fields.BooleanField', [], {'default': 'False'}), + 'is_superuser': ('django.db.models.fields.BooleanField', [], {'default': 'False'}), + 'last_login': ('django.db.models.fields.DateTimeField', [], {'default': 'datetime.datetime.now'}), + 'last_name': ('django.db.models.fields.CharField', [], {'max_length': '30', 'blank': 'True'}), + 'last_seen': ('django.db.models.fields.DateTimeField', [], {'default': 'datetime.datetime.now'}), + 'location': ('django.db.models.fields.CharField', [], {'max_length': '100', 'blank': 'True'}), + 'new_response_count': ('django.db.models.fields.IntegerField', [], {'default': '0'}), + 'password': ('django.db.models.fields.CharField', [], {'max_length': '128'}), + 'questions_per_page': ('django.db.models.fields.SmallIntegerField', [], {'default': '10'}), + 'real_name': ('django.db.models.fields.CharField', [], {'max_length': '100', 'blank': 'True'}), + 'reputation': ('django.db.models.fields.PositiveIntegerField', [], {'default': '1'}), + 'seen_response_count': ('django.db.models.fields.IntegerField', [], {'default': '0'}), + 'show_country': ('django.db.models.fields.BooleanField', [], {'default': 'False'}), + 'show_marked_tags': ('django.db.models.fields.BooleanField', [], {'default': 'True'}), + 'silver': ('django.db.models.fields.SmallIntegerField', [], {'default': '0'}), + 'status': ('django.db.models.fields.CharField', [], {'default': "'w'", 'max_length': '2'}), + 'subscribed_tags': ('django.db.models.fields.TextField', [], {'blank': 'True'}), + 'user_permissions': ('django.db.models.fields.related.ManyToManyField', [], {'to': "orm['auth.Permission']", 'symmetrical': 'False', 'blank': 'True'}), + 'username': ('django.db.models.fields.CharField', [], {'unique': 'True', 'max_length': '30'}), + 'website': ('django.db.models.fields.URLField', [], {'max_length': '200', 'blank': 'True'}) + }, + 'contenttypes.contenttype': { + 'Meta': {'ordering': "('name',)", 'unique_together': "(('app_label', 'model'),)", 'object_name': 'ContentType', 'db_table': "'django_content_type'"}, + 'app_label': ('django.db.models.fields.CharField', [], {'max_length': '100'}), + 'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}), + 'model': ('django.db.models.fields.CharField', [], {'max_length': '100'}), + 'name': ('django.db.models.fields.CharField', [], {'max_length': '100'}) + } + } + + complete_apps = ['askbot']
\ No newline at end of file diff --git a/askbot/models/__init__.py b/askbot/models/__init__.py index d5c13a0f..4fbabe9d 100644 --- a/askbot/models/__init__.py +++ b/askbot/models/__init__.py @@ -28,12 +28,14 @@ from askbot.models.question import Thread from askbot.skins import utils as skin_utils from askbot.mail import messages from askbot.models.question import QuestionView, AnonymousQuestion +from askbot.models.question import DraftQuestion from askbot.models.question import FavoriteQuestion from askbot.models.tag import Tag, MarkedTag from askbot.models.tag import get_group_names, get_groups from askbot.models.user import EmailFeedSetting, ActivityAuditStatus, Activity from askbot.models.user import GroupMembership, GroupProfile from askbot.models.post import Post, PostRevision, PostFlagReason, AnonymousAnswer +from askbot.models.post import DraftAnswer from askbot.models.reply_by_email import ReplyAddress from askbot.models import signals from askbot.models.badges import award_badges_signal, get_badge, BadgeData @@ -3394,8 +3396,10 @@ __all__ = [ 'QuestionView', 'FavoriteQuestion', 'AnonymousQuestion', + 'DraftQuestion', 'AnonymousAnswer', + 'DraftAnswer', 'Post', 'PostRevision', diff --git a/askbot/models/post.py b/askbot/models/post.py index e7624b1e..0ec6927a 100644 --- a/askbot/models/post.py +++ b/askbot/models/post.py @@ -1998,7 +1998,21 @@ class PostFlagReason(models.Model): app_label = 'askbot' +class DraftAnswer(models.Model): + """Provides space for draft answers, + note that unlike ``AnonymousAnswer`` the foreign key + is going to ``Thread`` as it should. + """ + thread = models.ForeignKey('Thread', related_name='draft_answers') + author = models.ForeignKey(User, related_name='draft_answers') + text = models.TextField(null=True) + + class Meta: + app_label = 'askbot' + + class AnonymousAnswer(DraftContent): + """Todo: re-route the foreign key to ``Thread``""" question = models.ForeignKey(Post, related_name='anonymous_answers') def publish(self, user): diff --git a/askbot/models/question.py b/askbot/models/question.py index d10b2c8f..7063b843 100644 --- a/askbot/models/question.py +++ b/askbot/models/question.py @@ -1068,6 +1068,19 @@ class FavoriteQuestion(models.Model): return '[%s] favorited at %s' %(self.user, self.added_at) +class DraftQuestion(models.Model): + """Provides space to solve unpublished draft + questions. Contents is used to populate the Ask form. + """ + author = models.ForeignKey(User) + title = models.CharField(max_length=300, null=True) + text = models.TextField(null=True) + tagnames = models.CharField(max_length=125, null=True) + + class Meta: + app_label = 'askbot' + + class AnonymousQuestion(DraftContent): """question that was asked before logging in maybe the name is a little misleading, the user still diff --git a/askbot/skins/common/media/js/post.js b/askbot/skins/common/media/js/post.js index 5b30b2bc..e8d521ed 100644 --- a/askbot/skins/common/media/js/post.js +++ b/askbot/skins/common/media/js/post.js @@ -206,6 +206,142 @@ var CPValidator = function(){ /** * @constructor + */ +var DraftPost = function() { + WrappedElement.call(this); +}; +inherits(DraftPost, WrappedElement); + +/** + * @return {string} + */ +DraftPost.prototype.getUrl = function() { + throw 'Not Implemented'; +}; + +/** + * @return {boolean} + */ +DraftPost.prototype.shouldSave = function() { + throw 'Not Implemented'; +}; + +/** + * @return {object} data dict + */ +DraftPost.prototype.getData = function() { + throw 'Not Implemented'; +}; + +DraftPost.prototype.backupData = function() { + this._old_data = this.getData(); +}; + + +DraftPost.prototype.getSaveHandler = function() { + var me = this; + return function(save_synchronously) { + if (me.shouldSave()) { + $.ajax({ + type: 'POST', + cache: false, + dataType: 'json', + async: save_synchronously ? false : true, + url: me.getUrl(), + data: me.getData(), + success: function(data) { + if (data['success'] && !save_synchronously) { + notify.show(gettext('Draft saved'), true); + } + me.backupData(); + } + }); + } + }; +}; + +DraftPost.prototype.decorate = function(element) { + this._element = element; + this.assignContentElements(); + this.backupData(); + setInterval(this.getSaveHandler(), 5000); + var me = this; + window.onbeforeunload = function() { + var saveHandler = me.getSaveHandler(); + saveHandler(true); + var msg = gettext("%s, we've saved your draft, but..."); + return interpolate(msg, [askbot['data']['userName']]); + }; +}; + + +/** + * @contstructor + */ +var DraftQuestion = function() { + DraftPost.call(this); +}; +inherits(DraftQuestion, DraftPost); + +DraftQuestion.prototype.getUrl = function() { + return askbot['urls']['saveDraftQuestion']; +}; + +DraftQuestion.prototype.shouldSave = function() { + var newd = this.getData(); + var oldd = this._old_data; + return ( + newd['title'] !== oldd['title'] || + newd['text'] !== oldd['text'] || + newd['tagnames'] !== oldd['tagnames'] + ); +}; + +DraftQuestion.prototype.getData = function() { + return { + 'title': this._title_element.val(), + 'text': this._text_element.val(), + 'tagnames': this._tagnames_element.val() + }; +}; + +DraftQuestion.prototype.assignContentElements = function() { + this._title_element = $('#id_title'); + this._text_element = $('#editor'); + this._tagnames_element = $('#id_tags'); +}; + +var DraftAnswer = function() { + DraftPost.call(this); +}; +inherits(DraftAnswer, DraftPost); + +DraftAnswer.prototype.setThreadId = function(id) { + this._threadId = id; +}; + +DraftAnswer.prototype.getUrl = function() { + return askbot['urls']['saveDraftAnswer']; +}; + +DraftAnswer.prototype.shouldSave = function() { + return this.getData()['text'] !== this._old_data['text']; +}; + +DraftAnswer.prototype.getData = function() { + return { + 'text': this._textElement.val(), + 'thread_id': this._threadId + }; +}; + +DraftAnswer.prototype.assignContentElements = function() { + this._textElement = $('#editor'); +}; + + +/** + * @constructor * @extends {SimpleControl} * @param {Comment} comment to upvote */ diff --git a/askbot/skins/common/media/js/utils.js b/askbot/skins/common/media/js/utils.js index da0e029b..30d2a64e 100644 --- a/askbot/skins/common/media/js/utils.js +++ b/askbot/skins/common/media/js/utils.js @@ -114,7 +114,7 @@ var setCheckBoxesIn = function(selector, value){ var notify = function() { var visible = false; return { - show: function(html) { + show: function(html, autohide) { if (html) { $("body").addClass('user-messages'); var par = $('<p class="notification"></p>'); @@ -123,7 +123,19 @@ var notify = function() { } $(".notify").fadeIn("slow"); visible = true; + if (autohide) { + setTimeout( + function() { + notify.close(false); + notify.clear(); + }, + 3000 + ); + } }, + clear: function() { + $('.notify').empty(); + }, close: function(doPostback) { if (doPostback) { $.post( diff --git a/askbot/skins/default/templates/ask.html b/askbot/skins/default/templates/ask.html index f0dae0ce..7826923b 100644 --- a/askbot/skins/default/templates/ask.html +++ b/askbot/skins/default/templates/ask.html @@ -36,6 +36,7 @@ {% endif %} <script type='text/javascript'> askbot['urls']['api_get_questions'] = '{% url api_get_questions %}'; + askbot['urls']['saveDraftQuestion'] = '{% url save_draft_question %}'; {% if settings.ENABLE_MATHJAX or settings.MARKUP_CODE_FRIENDLY %} var codeFriendlyMarkdown = true; {% else %} @@ -66,6 +67,17 @@ setupFormValidation($("#fmask"), CPValidator.getQuestionFormRules(), CPValidator.getQuestionFormMessages()); lanai.highlightSyntax(); + + if (askbot['data']['userIsAuthenticated']) { + var draftHandler = new DraftQuestion(); + draftHandler.decorate($(document)); + window.onbeforeunload = function() { + var saveHandler = draftHandler.getSaveHandler(); + saveHandler(true); + var msg = gettext("%s, we've saved your draft, but..."); + return interpolate(msg, [askbot['data']['userName']]); + }; + } }); </script> {% endblock %} diff --git a/askbot/skins/default/templates/meta/html_head_javascript.html b/askbot/skins/default/templates/meta/html_head_javascript.html index 6e480f8b..881244ed 100644 --- a/askbot/skins/default/templates/meta/html_head_javascript.html +++ b/askbot/skins/default/templates/meta/html_head_javascript.html @@ -5,6 +5,7 @@ {% if request.user.is_authenticated() %} askbot['data']['userIsAuthenticated'] = true; askbot['data']['userId'] = {{request.user.id}}; + askbot['data']['userName'] = '{{ request.user.username }}'; askbot['data']['userIsAdminOrMod'] = {% if request.user.is_administrator() or request.user.is_moderator() diff --git a/askbot/skins/default/templates/question.html b/askbot/skins/default/templates/question.html index 511c5086..c810aecb 100644 --- a/askbot/skins/default/templates/question.html +++ b/askbot/skins/default/templates/question.html @@ -94,7 +94,7 @@ {% if user_can_post_comment %} can_add = true; {% else %} - if (post_id in data['user_posts']){ + if (data['user_posts'] && post_id in data['user_posts']){ can_add = true; } {% endif %} diff --git a/askbot/skins/default/templates/question/javascript.html b/askbot/skins/default/templates/question/javascript.html index e76849c9..003d7f70 100644 --- a/askbot/skins/default/templates/question/javascript.html +++ b/askbot/skins/default/templates/question/javascript.html @@ -10,6 +10,7 @@ askbot['urls']['editComment'] = '{% url edit_comment %}'; askbot['urls']['deleteComment'] = '{% url delete_comment %}'; askbot['urls']['getComment'] = '{% url get_comment %}'; + askbot['urls']['saveDraftAnswer'] = '{% url save_draft_answer %}'; askbot['urls']['question_url_template'] = scriptUrl + '{{ 'question/'|transurl }}{{ "{{QuestionID}}/{{questionSlug}}" }}';{# yes it needs to be that whacky #} askbot['urls']['vote_url_template'] = scriptUrl + '{{ 'questions/'|transurl }}{{ "{{QuestionID}}/" }}{{ 'vote/'|transurl }}'; askbot['urls']['user_signin'] = '{{ settings.LOGIN_URL }}'; @@ -63,6 +64,12 @@ $("#fmanswer_button").hide(); }); {%endif%} + + if (askbot['data']['userIsAuthenticated']) { + var draftHandler = new DraftAnswer(); + draftHandler.setThreadId({{ thread.id }}); + draftHandler.decorate($(document)); + } }); $(window).bind('hashchange', animate_hashes); diff --git a/askbot/skins/default/templates/widgets/ask_form.html b/askbot/skins/default/templates/widgets/ask_form.html index 38613a3c..eaa3e154 100644 --- a/askbot/skins/default/templates/widgets/ask_form.html +++ b/askbot/skins/default/templates/widgets/ask_form.html @@ -3,7 +3,6 @@ <div class="form-item"> <div id="askFormBar"> {% if not request.user.is_authenticated() %} - <p>{% trans %}login to post question info{% endtrans %}</p> <p>{% trans %}<span class=\"strong big\">You are welcome to start submitting your question anonymously</span>. When you submit the post, you will be redirected to the login/signup page. Your question will be saved in the current session and will be published after you log in. Login/signup process is very simple. Login takes about 30 seconds, initial signup takes a minute or less.{% endtrans %}</p> {% else %} {% if settings.EMAIL_VALIDATION %} diff --git a/askbot/urls.py b/askbot/urls.py index 726722ff..c7c9c9f8 100644 --- a/askbot/urls.py +++ b/askbot/urls.py @@ -79,6 +79,16 @@ urlpatterns = patterns('', name = 'api_get_questions' ), url( + r'^save-draft-question/', + views.commands.save_draft_question, + name = 'save_draft_question' + ), + url( + r'^save-draft-answer/', + views.commands.save_draft_answer, + name = 'save_draft_answer' + ), + url( r'^%s%s$' % (_('questions/'), _('ask/')), views.writers.ask, name='ask' diff --git a/askbot/views/commands.py b/askbot/views/commands.py index 56848267..d4e7304e 100644 --- a/askbot/views/commands.py +++ b/askbot/views/commands.py @@ -1056,3 +1056,63 @@ def moderate_suggested_tag(request): tag.delete() else: raise Exception(forms.format_form_errors(form)) + + +@csrf.csrf_exempt +@decorators.ajax_only +@decorators.post_only +def save_draft_question(request): + """saves draft questions""" + #todo: allow drafts for anonymous users + if request.user.is_anonymous(): + return + + form = forms.DraftQuestionForm(request.POST) + if form.is_valid(): + title = form.cleaned_data.get('title', '') + text = form.cleaned_data.get('text', '') + tagnames = form.cleaned_data.get('tagnames', '') + if title or text or tagnames: + try: + draft = models.DraftQuestion.objects.get(author=request.user) + except models.DraftQuestion.DoesNotExist: + draft = models.DraftQuestion() + + draft.title = title + draft.text = text + draft.tagnames = tagnames + draft.author = request.user + draft.save() + + +@csrf.csrf_exempt +@decorators.ajax_only +@decorators.post_only +def save_draft_answer(request): + """saves draft answers""" + #todo: allow drafts for anonymous users + if request.user.is_anonymous(): + return + + import pdb + pdb.set_trace() + + form = forms.DraftAnswerForm(request.POST) + if form.is_valid(): + thread_id = form.cleaned_data['thread_id'] + try: + thread = models.Thread.objects.get(id=thread_id) + except models.Thread.DoesNotExist: + return + try: + draft = models.DraftAnswer.objects.get( + thread=thread, + author=request.user + ) + except models.DraftAnswer.DoesNotExist: + draft = models.DraftAnswer() + + draft.author = request.user + draft.thread = thread + draft.text = form.cleaned_data.get('text', '') + draft.save() diff --git a/askbot/views/writers.py b/askbot/views/writers.py index 2791557e..b4c58547 100644 --- a/askbot/views/writers.py +++ b/askbot/views/writers.py @@ -222,6 +222,10 @@ def ask(request):#view used to ask a new question group_id = form.cleaned_data.get('group_id', None) if request.user.is_authenticated(): + drafts = models.DraftQuestion.objects.filter( + author=request.user + ) + drafts.delete() try: question = request.user.post_question( title = title, @@ -258,11 +262,21 @@ def ask(request):#view used to ask a new question if request.method == 'GET': form = forms.AskForm() + draft_title = '' + draft_text = '' + draft_tagnames = '' + if request.user.is_authenticated(): + drafts = models.DraftQuestion.objects.filter(author=request.user) + if len(drafts) > 0: + draft = drafts[0] + draft_title = draft.title + draft_text = draft.text + draft_tagnames = draft.tagnames form.initial = { - 'title': request.REQUEST.get('title', ''), - 'text': request.REQUEST.get('text', ''), - 'tags': request.REQUEST.get('tags', ''), + 'title': request.REQUEST.get('title', draft_title), + 'text': request.REQUEST.get('text', draft_text), + 'tags': request.REQUEST.get('tags', draft_tagnames), 'wiki': request.REQUEST.get('wiki', False), 'ask_anonymously': request.REQUEST.get('ask_anonymousy', False), 'post_privately': request.REQUEST.get('post_privately', False) @@ -271,7 +285,7 @@ def ask(request):#view used to ask a new question try: group_id = int(request.GET.get('group_id', None)) form.initial['group_id'] = group_id - except Exeption: + except Exception: pass data = { |