summaryrefslogtreecommitdiffstats
path: root/askbot/forms.py
diff options
context:
space:
mode:
authorEvgeny Fadeev <evgeny.fadeev@gmail.com>2012-07-30 02:02:44 -0400
committerEvgeny Fadeev <evgeny.fadeev@gmail.com>2012-07-30 02:02:44 -0400
commit9c4317418904e849845da32c35f1eb225b0f4f78 (patch)
tree9f08e07c50ad5ce56e2171810b91e71480a13c5a /askbot/forms.py
parenta4445bf35f18b017cf7c9ccb2daf0893253844ae (diff)
downloadaskbot-9c4317418904e849845da32c35f1eb225b0f4f78.tar.gz
askbot-9c4317418904e849845da32c35f1eb225b0f4f78.tar.bz2
askbot-9c4317418904e849845da32c35f1eb225b0f4f78.zip
completed the "admins can post under fake accounts" feature
Diffstat (limited to 'askbot/forms.py')
-rw-r--r--askbot/forms.py613
1 files changed, 400 insertions, 213 deletions
diff --git a/askbot/forms.py b/askbot/forms.py
index 18fe7537..64337883 100644
--- a/askbot/forms.py
+++ b/askbot/forms.py
@@ -1,11 +1,13 @@
+"""Forms, custom form fields and related utility functions
+used in AskBot"""
import re
from django import forms
from askbot import const
+from django.forms.util import ErrorList
from django.utils.translation import ugettext_lazy as _
from django.utils.translation import ungettext_lazy, string_concat
from django.utils.text import get_text_list
from django.contrib.auth.models import User
-from django.contrib.contenttypes.models import ContentType
from django_countries import countries
from askbot.utils.forms import NextUrlField, UserNameField
from askbot.mail import extract_first_email_address
@@ -13,6 +15,7 @@ from recaptcha_works.fields import RecaptchaField
from askbot.conf import settings as askbot_settings
import logging
+
def cleanup_dict(dictionary, key, empty_value):
"""deletes key from dictionary if it exists
and the corresponding value equals the empty_value
@@ -20,13 +23,27 @@ def cleanup_dict(dictionary, key, empty_value):
if key in dictionary and dictionary[key] == empty_value:
del dictionary[key]
+
def format_form_errors(form):
+ """Formats form errors in HTML
+ if there is only one error - returns a plain string
+ if more than one, returns an unordered list of errors
+ in HTML format.
+ If there are no errors, returns empty string
+ """
if form.errors:
errors = form.errors.values()
if len(errors) == 1:
return errors[0]
else:
- return 'hahahahah'
+ result = '<ul>'
+ for error in errors:
+ result += '<li>%s</li>' % error
+ result += '</ul>'
+ return result
+ else:
+ return ''
+
def clean_marked_tagnames(tagnames):
"""return two strings - one containing tagnames
@@ -35,7 +52,7 @@ def clean_marked_tagnames(tagnames):
wildcard tags are those that have an asterisk at the end
the function does not verify that the tag names are valid
"""
- if askbot_settings.USE_WILDCARD_TAGS == False:
+ if askbot_settings.USE_WILDCARD_TAGS is False:
return tagnames, list()
pure_tags = list()
@@ -53,7 +70,8 @@ def clean_marked_tagnames(tagnames):
return pure_tags, wildcards
-def filter_choices(remove_choices = None, from_choices = None):
+
+def filter_choices(remove_choices=None, from_choices=None):
"""a utility function that will remove choice tuples
usable for the forms.ChoicesField from
``from_choices``, the removed ones will be those given
@@ -73,12 +91,47 @@ def filter_choices(remove_choices = None, from_choices = None):
if choice == choice_to_test[0]:
remove = True
break
- if remove == False:
- filtered_choices += ( choice_to_test, )
+ if remove is False:
+ filtered_choices += (choice_to_test, )
return filtered_choices
-COUNTRY_CHOICES = (('unknown',_('select country')),) + countries.COUNTRIES
+
+def need_mandatory_tags():
+ """true, if list of mandatory tags is not empty"""
+ from askbot import models
+ return (
+ askbot_settings.TAGS_ARE_REQUIRED
+ and len(models.tag.get_mandatory_tags()) > 0
+ )
+
+
+def mandatory_tag_missing_in_list(tag_strings):
+ """true, if mandatory tag is not present in the list
+ of ``tag_strings``"""
+ from askbot import models
+ mandatory_tags = models.tag.get_mandatory_tags()
+ for mandatory_tag in mandatory_tags:
+ for tag_string in tag_strings:
+ if tag_strings_match(tag_string, mandatory_tag):
+ return False
+ return True
+
+
+def tag_strings_match(tag_string, mandatory_tag):
+ """true if tag string matches the mandatory tag,
+ the comparison is not symmetric if tag_string ends with a
+ wildcard (asterisk)
+ """
+ if mandatory_tag.endswith('*'):
+ return tag_string.startswith(mandatory_tag[:-1])
+ else:
+ return tag_string == mandatory_tag
+
+
+
+COUNTRY_CHOICES = (('unknown', _('select country')),) + countries.COUNTRIES
+
class CountryField(forms.ChoiceField):
"""this is better placed into the django_coutries app"""
@@ -100,10 +153,13 @@ class CountryField(forms.ChoiceField):
return None
return value
+
class CountedWordsField(forms.CharField):
-
+ """a field where a number of words is expected
+ to be in a certain range"""
+
def __init__(
- self, min_words = 0, max_words = 9999, field_name = None,
+ self, min_words=0, max_words=9999, field_name=None,
*args, **kwargs
):
self.min_words = min_words
@@ -144,28 +200,38 @@ class CountedWordsField(forms.CharField):
class DomainNameField(forms.CharField):
+ """Field for Internet Domain Names
+ todo: maybe there is a standard field for this?
+ """
def clean(self, value):
#find a better regex, taking into account tlds
domain_re = re.compile(r'[a-zA-Z\d]+(\.[a-zA-Z\d]+)+')
if domain_re.match(value):
return value
else:
- raise forms.ValidationError('%s is not a valid domain name' % value)
+ raise forms.ValidationError(
+ '%s is not a valid domain name' % value
+ )
class TitleField(forms.CharField):
+ """Fild receiving question title"""
def __init__(self, *args, **kwargs):
super(TitleField, self).__init__(*args, **kwargs)
self.required = True
self.widget = forms.TextInput(
- attrs={'size' : 70, 'autocomplete' : 'off'}
- )
+ attrs={'size': 70, 'autocomplete': 'off'}
+ )
self.max_length = 255
- self.label = _('title')
- self.help_text = _('please enter a descriptive title for your question')
+ self.label = _('title')
+ self.help_text = _(
+ 'please enter a descriptive title for your question'
+ )
self.initial = ''
def clean(self, value):
+ """cleans the field for minimum and maximum length
+ also is supposed to work for unicode non-ascii characters"""
if value is None:
value = ''
if len(value) < askbot_settings.MIN_TITLE_LENGTH:
@@ -192,21 +258,22 @@ class TitleField(forms.CharField):
) % self.max_length
)
- return value.strip() # TODO: test me
+ return value.strip() # TODO: test me
+
class EditorField(forms.CharField):
- """EditorField is subclassed by the
+ """EditorField is subclassed by the
:class:`QuestionEditorField` and :class:`AnswerEditorField`
"""
length_error_template_singular = 'post content must be > %d character',
length_error_template_plural = 'post content must be > %d characters',
- min_length = 10#sentinel default value
+ min_length = 10 # sentinel default value
def __init__(self, *args, **kwargs):
super(EditorField, self).__init__(*args, **kwargs)
self.required = True
- self.widget = forms.Textarea(attrs={'id':'editor'})
- self.label = _('content')
+ self.widget = forms.Textarea(attrs={'id': 'editor'})
+ self.label = _('content')
self.help_text = u''
self.initial = ''
@@ -218,32 +285,44 @@ class EditorField(forms.CharField):
self.length_error_template_singular,
self.length_error_template_plural,
self.min_length
- ) % self.min_length
+ ) % self.min_length
raise forms.ValidationError(msg)
return value
+
class QuestionEditorField(EditorField):
+ """Editor field for the questions"""
+
def __init__(self, *args, **kwargs):
super(QuestionEditorField, self).__init__(*args, **kwargs)
- self.length_error_template_singular = 'question body must be > %d character'
- self.length_error_template_plural = 'question body must be > %d characters'
+ self.length_error_template_singular = \
+ 'question body must be > %d character'
+ self.length_error_template_plural = \
+ 'question body must be > %d characters'
self.min_length = askbot_settings.MIN_QUESTION_BODY_LENGTH
+
class AnswerEditorField(EditorField):
+ """Editor field for answers"""
+
def __init__(self, *args, **kwargs):
super(AnswerEditorField, self).__init__(*args, **kwargs)
self.length_error_template_singular = 'answer must be > %d character'
self.length_error_template_plural = 'answer must be > %d characters'
self.min_length = askbot_settings.MIN_ANSWER_BODY_LENGTH
+
class TagNamesField(forms.CharField):
+ """field that receives AskBot tag names"""
+
def __init__(self, *args, **kwargs):
super(TagNamesField, self).__init__(*args, **kwargs)
self.required = askbot_settings.TAGS_ARE_REQUIRED
- self.widget = forms.TextInput(attrs={'size' : 50, 'autocomplete' : 'off'})
+ self.widget = forms.TextInput(
+ attrs={'size': 50, 'autocomplete': 'off'}
+ )
self.max_length = 255
self.label = _('tags')
- #self.help_text = _('please use space to separate tags (this enables autocomplete feature)')
self.help_text = ungettext_lazy(
'Tags are short keywords, with no spaces within. '
'Up to %(max_tags)d tag can be used.',
@@ -253,38 +332,16 @@ class TagNamesField(forms.CharField):
) % {'max_tags': askbot_settings.MAX_TAGS_PER_POST}
self.initial = ''
- def need_mandatory_tags(self):
- """true, if list of mandatory tags is not empty"""
- from askbot import models
- return askbot_settings.TAGS_ARE_REQUIRED and len(models.tag.get_mandatory_tags()) > 0
-
- def tag_string_matches(self, tag_string, mandatory_tag):
- """true if tag string matches the mandatory tag"""
- if mandatory_tag.endswith('*'):
- return tag_string.startswith(mandatory_tag[:-1])
- else:
- return tag_string == mandatory_tag
-
- def mandatory_tag_missing(self, tag_strings):
- """true, if mandatory tag is not present in the list
- of ``tag_strings``"""
- from askbot import models
- mandatory_tags = models.tag.get_mandatory_tags()
- for mandatory_tag in mandatory_tags:
- for tag_string in tag_strings:
- if self.tag_string_matches(tag_string, mandatory_tag):
- return False
- return True
-
def clean(self, value):
from askbot import models
value = super(TagNamesField, self).clean(value)
data = value.strip()
if len(data) < 1:
if askbot_settings.TAGS_ARE_REQUIRED:
- raise forms.ValidationError(_('tags are required'))
+ raise forms.ValidationError(_('tags are required'))
else:
- return ''#don't test for required characters when tags is ''
+ #don't test for required characters when tags is ''
+ return ''
split_re = re.compile(const.TAG_SPLIT_REGEX)
tag_strings = split_re.split(data)
entered_tags = []
@@ -294,11 +351,11 @@ class TagNamesField(forms.CharField):
msg = ungettext_lazy(
'please use %(tag_count)d tag or less',
'please use %(tag_count)d tags or less',
- tag_count) % {'tag_count':max_tags}
+ tag_count) % {'tag_count': max_tags}
raise forms.ValidationError(msg)
- if self.need_mandatory_tags():
- if self.mandatory_tag_missing(tag_strings):
+ if need_mandatory_tags():
+ if mandatory_tag_missing_in_list(tag_strings):
msg = _(
'At least one of the following tags is required : %(tags)s'
) % {'tags': get_text_list(models.tag.get_mandatory_tags())}
@@ -307,18 +364,22 @@ class TagNamesField(forms.CharField):
for tag in tag_strings:
tag_length = len(tag)
if tag_length > askbot_settings.MAX_TAG_LENGTH:
- #singular form is odd in english, but required for pluralization
- #in other languages
- msg = ungettext_lazy('each tag must be shorter than %(max_chars)d character',#odd but added for completeness
- 'each tag must be shorter than %(max_chars)d characters',
- tag_length) % {'max_chars':tag_length}
+ #singular form is odd in english, but
+ #required for pluralization
+ #in other languages, odd but added for completeness
+ msg = ungettext_lazy(
+ 'each tag must be shorter than %(max_chars)d character',
+ 'each tag must be shorter than %(max_chars)d characters',
+ tag_length
+ ) % {'max_chars': tag_length}
raise forms.ValidationError(msg)
#todo - this needs to come from settings
tagname_re = re.compile(const.TAG_REGEX, re.UNICODE)
if not tagname_re.search(tag):
raise forms.ValidationError(_(
- 'In tags, please use letters, numbers and characters "-+.#"'
+ 'In tags, please use letters, '
+ 'numbers and characters "-+.#"'
))
#only keep unique tags
if tag not in entered_tags:
@@ -340,7 +401,7 @@ class TagNamesField(forms.CharField):
#because we need tag name cases to be the same
#as those stored in the database
stored_tag = models.Tag.objects.get(
- name__iexact = entered_tag
+ name__iexact=entered_tag
)
if stored_tag.name not in cleaned_entered_tags:
cleaned_entered_tags.append(stored_tag.name)
@@ -349,30 +410,54 @@ class TagNamesField(forms.CharField):
return u' '.join(cleaned_entered_tags)
+
class WikiField(forms.BooleanField):
+ """Rendered as checkbox turning post into
+ "community wiki"
+ """
+
def __init__(self, *args, **kwargs):
super(WikiField, self).__init__(*args, **kwargs)
self.required = False
self.initial = False
- self.label = _('community wiki (karma is not awarded & many others can edit wiki post)')
- self.help_text = _('if you choose community wiki option, the question and answer do not generate points and name of author will not be shown')
+ self.label = _(
+ 'community wiki (karma is not awarded & '
+ 'many others can edit wiki post)'
+ )
+ self.help_text = _(
+ 'if you choose community wiki option, the question '
+ 'and answer do not generate points and name of '
+ 'author will not be shown'
+ )
+
def clean(self, value):
return value and askbot_settings.WIKI_ON
+
class EmailNotifyField(forms.BooleanField):
+ """Rendered as checkbox which turns on
+ email notifications on the post"""
def __init__(self, *args, **kwargs):
super(EmailNotifyField, self).__init__(*args, **kwargs)
self.required = False
self.widget.attrs['class'] = 'nomargin'
+
class SummaryField(forms.CharField):
+
def __init__(self, *args, **kwargs):
super(SummaryField, self).__init__(*args, **kwargs)
self.required = False
- self.widget = forms.TextInput(attrs={'size' : 50, 'autocomplete' : 'off'})
+ self.widget = forms.TextInput(
+ attrs={'size': 50, 'autocomplete': 'off'}
+ )
self.max_length = 300
- self.label = _('update summary:')
- self.help_text = _('enter a brief summary of your revision (e.g. fixed spelling, grammar, improved style, this field is optional)')
+ self.label = _('update summary:')
+ self.help_text = _(
+ 'enter a brief summary of your revision (e.g. '
+ 'fixed spelling, grammar, improved style, this '
+ 'field is optional)'
+ )
class DumpUploadForm(forms.Form):
@@ -382,6 +467,7 @@ class DumpUploadForm(forms.Form):
"""
dump_file = forms.FileField()
+
class ShowQuestionForm(forms.Form):
"""Cleans data necessary to access answers and comments
by the respective comment or answer id - necessary
@@ -389,10 +475,10 @@ class ShowQuestionForm(forms.Form):
on the page other than the first page of answers to a question.
Same for the answers that are shown on the later pages.
"""
- answer = forms.IntegerField(required = False)
- comment = forms.IntegerField(required = False)
- page = forms.IntegerField(required = False)
- sort = forms.CharField(required = False)
+ answer = forms.IntegerField(required=False)
+ comment = forms.IntegerField(required=False)
+ page = forms.IntegerField(required=False)
+ sort = forms.CharField(required=False)
def __init__(self, data, default_sort_method):
super(ShowQuestionForm, self).__init__(data)
@@ -436,6 +522,7 @@ class ShowQuestionForm(forms.Form):
self.cleaned_data = out_data
return out_data
+
class ChangeUserReputationForm(forms.Form):
"""Form that allows moderators and site administrators
to adjust reputation of users.
@@ -445,13 +532,15 @@ class ChangeUserReputationForm(forms.Form):
"""
user_reputation_delta = forms.IntegerField(
- min_value = 1,
- label = _('Enter number of points to add or subtract')
- )
- comment = forms.CharField(max_length = 128)
+ min_value=1,
+ label=_(
+ 'Enter number of points to add or subtract'
+ )
+ )
+ comment = forms.CharField(max_length=128)
def clean_comment(self):
- if 'comment' in self.cleaned_data:
+ if 'comment' in self.cleaned_data:
comment = self.cleaned_data['comment'].strip()
if comment == '':
del self.cleaned_data['comment']
@@ -485,9 +574,7 @@ class ChangeUserStatusForm(forms.Form):
"moderation" tab
"""
- user_status = forms.ChoiceField(
- label = _('Change status to'),
- )
+ user_status = forms.ChoiceField(label=_('Change status to'))
def __init__(self, *arg, **kwarg):
@@ -508,12 +595,12 @@ class ChangeUserStatusForm(forms.Form):
#remove current status of the "subject" user from choices
user_status_choices = filter_choices(
- remove_choices = [subject.status, ],
- from_choices = user_status_choices
+ remove_choices=[subject.status, ],
+ from_choices=user_status_choices
)
#add prompt option
- user_status_choices = ( ('select', _('which one?')), ) \
+ user_status_choices = (('select', _('which one?')), ) \
+ user_status_choices
self.fields['user_status'].choices = user_status_choices
@@ -561,41 +648,39 @@ class ChangeUserStatusForm(forms.Form):
msg = _(
'If you wish to change %(username)s\'s status, '
'please make a meaningful selection.'
- ) % {'username': self.subject.username }
+ ) % {'username': self.subject.username}
raise forms.ValidationError(msg)
return self.cleaned_data
+
class SendMessageForm(forms.Form):
subject_line = forms.CharField(
- label = _('Subject line'),
- max_length = 64,
- widget = forms.TextInput(
- attrs = {'size':64},
- )
- )
+ label=_('Subject line'),
+ max_length=64,
+ widget=forms.TextInput(attrs={'size': 64}, )
+ )
body_text = forms.CharField(
- label = _('Message text'),
- max_length = 1600,
- widget = forms.Textarea(
- attrs = {'cols':64}
- )
+ label=_('Message text'),
+ max_length=1600,
+ widget=forms.Textarea(attrs={'cols': 64})
)
class NotARobotForm(forms.Form):
recaptcha = RecaptchaField(
- private_key = askbot_settings.RECAPTCHA_SECRET,
- public_key = askbot_settings.RECAPTCHA_KEY
+ private_key=askbot_settings.RECAPTCHA_SECRET,
+ public_key=askbot_settings.RECAPTCHA_KEY
)
+
class FeedbackForm(forms.Form):
name = forms.CharField(label=_('Your name (optional):'), required=False)
email = forms.EmailField(label=_('Email:'), required=False)
message = forms.CharField(
label=_('Your message:'),
max_length=800,
- widget=forms.Textarea(attrs={'cols':60})
+ widget=forms.Textarea(attrs={'cols': 60})
)
no_email = forms.BooleanField(
label=_("I don't want to give my email or receive a response:"),
@@ -612,19 +697,21 @@ class FeedbackForm(forms.Form):
def _add_recaptcha_field(self):
self.fields['recaptcha'] = RecaptchaField(
- private_key = askbot_settings.RECAPTCHA_SECRET,
- public_key = askbot_settings.RECAPTCHA_KEY
- )
+ private_key=askbot_settings.RECAPTCHA_SECRET,
+ public_key=askbot_settings.RECAPTCHA_KEY
+ )
def clean(self):
super(FeedbackForm, self).clean()
if not self.is_auth:
- if not self.cleaned_data['no_email'] and not self.cleaned_data['email']:
+ if not self.cleaned_data['no_email'] \
+ and not self.cleaned_data['email']:
msg = _('Please mark "I dont want to give my mail" field.')
self._errors['email'] = self.error_class([msg])
return self.cleaned_data
+
class FormWithHideableFields(object):
"""allows to swap a field widget to HiddenInput() and back"""
@@ -646,7 +733,81 @@ class FormWithHideableFields(object):
if name in self.__hidden_fields:
self.fields[name] = self.__hidden_fields.pop(name)
-class AskForm(forms.Form, FormWithHideableFields):
+
+class PostAsSomeoneForm(forms.Form):
+ post_author_username = forms.CharField(
+ initial=_('User name:'),
+ help_text=_(
+ 'Enter name to post on behalf of someone else. '
+ 'Can create new accounts.'
+ ),
+ required=False,
+ widget=forms.TextInput(attrs={'class': 'tipped-input'})
+ )
+ post_author_email = forms.CharField(
+ initial=_('Email address:'),
+ required=False,
+ widget=forms.TextInput(attrs={'class': 'tipped-input'})
+ )
+
+ def get_post_user(self, user):
+ """returns user on whose behalf the post or a revision
+ is being made
+ """
+ username = self.cleaned_data['post_author_username']
+ email= self.cleaned_data['post_author_email']
+ if user.is_administrator() and username and email:
+ post_user = user.get_or_create_user(username, email)
+ else:
+ post_user = user
+ return post_user
+
+ def clean_post_author_username(self):
+ """if value is the same as initial, it is reset to
+ empty string
+ todo: maybe better to have field where initial value is invalid,
+ then we would not have to have two almost identical clean functions?
+ """
+ username = self.cleaned_data.get('post_author_username', '')
+ initial_username = unicode(self.fields['post_author_username'].initial)
+ if username == initial_username:
+ self.cleaned_data['post_author_username'] = ''
+ return self.cleaned_data['post_author_username']
+
+ def clean_post_author_email(self):
+ """if value is the same as initial, it is reset to
+ empty string"""
+ email = self.cleaned_data.get('post_author_email', '')
+ initial_email = unicode(self.fields['post_author_email'].initial)
+ if email == initial_email:
+ email = ''
+ if email != '':
+ email = forms.EmailField().clean(email)
+ self.cleaned_data['post_author_email'] = email
+ return email
+
+ def clean(self):
+ """requires email address if user name is given"""
+ username = self.cleaned_data.get('post_author_username', '')
+ email = self.cleaned_data.get('post_author_email', '')
+ if username == '' and email:
+ username_errors = self._errors.get(
+ 'post_author_username',
+ ErrorList()
+ )
+ username_errors.append(_('User name is required with the email'))
+ self._errors['post_author_username'] = username_errors
+ raise forms.ValidationError('missing user name')
+ elif email == '' and username:
+ email_errors = self._errors.get('post_author_email', ErrorList())
+ email_errors.append(_('Email is required if user name is added'))
+ self._errors['post_author_email'] = email_errors
+ raise forms.ValidationError('missing email')
+
+ return self.cleaned_data
+
+
+class AskForm(PostAsSomeoneForm, FormWithHideableFields):
"""the form used to askbot questions
field ask_anonymously is shown to the user if the
if ALLOW_ASK_ANONYMOUSLY live setting is True
@@ -654,45 +815,43 @@ class AskForm(forms.Form, FormWithHideableFields):
in the cleaned data, and will evaluate to False if the
settings forbids anonymous asking
"""
- title = TitleField()
- text = QuestionEditorField()
- tags = TagNamesField()
+ title = TitleField()
+ text = QuestionEditorField()
+ tags = TagNamesField()
wiki = WikiField()
ask_anonymously = forms.BooleanField(
- label = _('ask anonymously'),
- help_text = _(
+ label=_('ask anonymously'),
+ help_text=_(
'Check if you do not want to reveal your name '
'when asking this question'
),
- required = False,
- )
- openid = forms.CharField(required=False, max_length=255, widget=forms.TextInput(attrs={'size' : 40, 'class':'openid-input'}))
- user = forms.CharField(
required=False,
- max_length=255,
- label="User",
- help_text=_("Enter the username to post this as. New users are automatically created."),
- widget=forms.TextInput(attrs={'size' : 35}))
- email = forms.CharField(required=False, max_length=255, widget=forms.TextInput(attrs={'size' : 35}))
+ )
+ openid = forms.CharField(
+ required=False, max_length=255,
+ widget=forms.TextInput(attrs={'size': 40, 'class': 'openid-input'})
+ )
def __init__(self, *args, **kwargs):
super(AskForm, self).__init__(*args, **kwargs)
#hide ask_anonymously field
- if askbot_settings.ALLOW_ASK_ANONYMOUSLY == False:
+ if askbot_settings.ALLOW_ASK_ANONYMOUSLY is False:
self.hide_field('ask_anonymously')
def clean_ask_anonymously(self):
"""returns false if anonymous asking is not allowed
"""
- if askbot_settings.ALLOW_ASK_ANONYMOUSLY == False:
+ if askbot_settings.ALLOW_ASK_ANONYMOUSLY is False:
self.cleaned_data['ask_anonymously'] = False
return self.cleaned_data['ask_anonymously']
+
ASK_BY_EMAIL_SUBJECT_HELP = _(
'Subject line is expected in the format: '
'[tag1, tag2, tag3,...] question title'
)
+
class AskByEmailForm(forms.Form):
""":class:`~askbot.forms.AskByEmailForm`
validates question data, where question was posted
@@ -711,12 +870,13 @@ class AskByEmailForm(forms.Form):
* ``email`` - email address
* ``title`` - question title
* ``tagnames`` - tag names all in one string
- * ``body_text`` - body of question text - a pass-through, no extra validation
+ * ``body_text`` - body of question text -
+ a pass-through, no extra validation
"""
- sender = forms.CharField(max_length = 255)
+ sender = forms.CharField(max_length=255)
subject = forms.CharField(
- max_length = 255,
- error_messages = {
+ max_length=255,
+ error_messages={
'required': ASK_BY_EMAIL_SUBJECT_HELP
}
)
@@ -748,17 +908,19 @@ class AskByEmailForm(forms.Form):
match = subject_re.match(raw_subject)
if match:
#make raw tags comma-separated
- if match.group(1) is None:#no tags
+ if match.group(1) is None: # no tags
self.cleaned_data['tagnames'] = ''
else:
- tagnames = match.group(1).replace(';',',')
+ tagnames = match.group(1).replace(';', ',')
#pre-process tags
tag_list = [tag.strip() for tag in tagnames.split(',')]
tag_list = [re.sub(r'\s+', ' ', tag) for tag in tag_list]
+
if askbot_settings.REPLACE_SPACE_WITH_DASH_IN_EMAILED_TAGS:
tag_list = [tag.replace(' ', '-') for tag in tag_list]
- tagnames = ' '.join(tag_list)#todo: use tag separator char here
+ #todo: use tag separator char here
+ tagnames = ' '.join(tag_list)
#clean tags - may raise ValidationError
self.cleaned_data['tagnames'] = TagNamesField().clean(tagnames)
@@ -770,27 +932,28 @@ class AskByEmailForm(forms.Form):
raise forms.ValidationError(ASK_BY_EMAIL_SUBJECT_HELP)
return self.cleaned_data['subject']
-class AnswerForm(forms.Form):
- text = AnswerEditorField()
- wiki = WikiField()
- openid = forms.CharField(required=False, max_length=255, widget=forms.TextInput(attrs={'size' : 40, 'class':'openid-input'}))
- user = forms.CharField(
- required=False,
- max_length=255,
- label="User",
- help_text=_("Enter the username to post this as. New users are automatically created."),
- widget=forms.TextInput(attrs={'size' : 35}))
- email = forms.CharField(required=False, max_length=255, widget=forms.TextInput(attrs={'size' : 35}))
- email_notify = EmailNotifyField(initial = False)
+
+class AnswerForm(PostAsSomeoneForm):
+ text = AnswerEditorField()
+ wiki = WikiField()
+ openid = forms.CharField(
+ required=False, max_length=255,
+ widget=forms.TextInput(attrs={'size': 40, 'class': 'openid-input'})
+ )
+ email_notify = EmailNotifyField(initial=False)
+
def __init__(self, *args, **kwargs):
super(AnswerForm, self).__init__(*args, **kwargs)
- self.fields['email_notify'].widget.attrs['id'] = 'question-subscribe-updates'
+ self.fields['email_notify'].widget.attrs['id'] = \
+ 'question-subscribe-updates'
+
class VoteForm(forms.Form):
"""form used in ajax vote view (only comment_upvote so far)
"""
post_id = forms.IntegerField()
- cancel_vote = forms.CharField()#char because it is 'true' or 'false' as string
+ # char because it is 'true' or 'false' as string
+ cancel_vote = forms.CharField()
def clean_cancel_vote(self):
val = self.cleaned_data['cancel_vote']
@@ -800,7 +963,9 @@ class VoteForm(forms.Form):
result = False
else:
del self.cleaned_data['cancel_vote']
- raise forms.ValidationError('either "true" or "false" strings expected')
+ raise forms.ValidationError(
+ 'either "true" or "false" strings expected'
+ )
self.cleaned_data['cancel_vote'] = result
return self.cleaned_data['cancel_vote']
@@ -808,50 +973,58 @@ class VoteForm(forms.Form):
class CloseForm(forms.Form):
reason = forms.ChoiceField(choices=const.CLOSE_REASONS)
+
class RetagQuestionForm(forms.Form):
tags = TagNamesField()
- # initialize the default values
+
def __init__(self, question, *args, **kwargs):
+ """initialize the default values"""
super(RetagQuestionForm, self).__init__(*args, **kwargs)
self.fields['tags'].initial = question.thread.tagnames
+
class RevisionForm(forms.Form):
"""
Lists revisions of a Question or Answer
"""
- revision = forms.ChoiceField(widget=forms.Select(attrs={'style' : 'width:520px'}))
+ revision = forms.ChoiceField(
+ widget=forms.Select(
+ attrs={'style': 'width:520px'}
+ )
+ )
def __init__(self, post, latest_revision, *args, **kwargs):
super(RevisionForm, self).__init__(*args, **kwargs)
revisions = post.revisions.values_list(
- 'revision', 'author__username', 'revised_at', 'summary')
+ 'revision', 'author__username', 'revised_at', 'summary'
+ )
date_format = '%c'
- self.fields['revision'].choices = [
- (r[0], u'%s - %s (%s) %s' % (r[0], r[1], r[2].strftime(date_format), r[3]))
- for r in revisions]
+ rev_choices = list()
+ for r in revisions:
+ rev_details = u'%s - %s (%s) %s' % (
+ r[0], r[1], r[2].strftime(date_format), r[3]
+ )
+ rev_choices.append((r[0], rev_details))
+
+ self.fields['revision'].choices = rev_choices
self.fields['revision'].initial = latest_revision.revision
-class EditQuestionForm(forms.Form, FormWithHideableFields):
- title = TitleField()
- text = QuestionEditorField()
- tags = TagNamesField()
+
+class EditQuestionForm(PostAsSomeoneForm, FormWithHideableFields):
+ title = TitleField()
+ text = QuestionEditorField()
+ tags = TagNamesField()
summary = SummaryField()
wiki = WikiField()
reveal_identity = forms.BooleanField(
- help_text = _(
+ help_text=_(
'You have asked this question anonymously, '
'if you decide to reveal your identity, please check '
'this box.'
),
- label = _('reveal identity'),
- required = False,
- )
- user_author = forms.CharField(
+ label=_('reveal identity'),
required=False,
- max_length=255,
- label="User",
- help_text=_("Enter the username to post this as. New users are automatically created."),
- widget=forms.TextInput(attrs={'size' : 35}))
+ )
#todo: this is odd that this form takes question as an argument
def __init__(self, *args, **kwargs):
@@ -871,8 +1044,8 @@ class EditQuestionForm(forms.Form, FormWithHideableFields):
def can_stay_anonymous(self):
"""determines if the user cat keep editing the question
anonymously"""
- return (askbot_settings.ALLOW_ASK_ANONYMOUSLY \
- and self.question.is_anonymous \
+ return (askbot_settings.ALLOW_ASK_ANONYMOUSLY
+ and self.question.is_anonymous
and self.user.is_owner_of(self.question)
)
@@ -898,7 +1071,7 @@ class EditQuestionForm(forms.Form, FormWithHideableFields):
"""
value = self.cleaned_data['reveal_identity']
if self.question.is_anonymous:
- if value == True:
+ if value is True:
if self.user.is_owner_of(self.question):
#regardless of the ALLOW_ASK_ANONYMOUSLY
return True
@@ -916,7 +1089,7 @@ class EditQuestionForm(forms.Form, FormWithHideableFields):
else:
can_ask_anon = askbot_settings.ALLOW_ASK_ANONYMOUSLY
is_owner = self.user.is_owner_of(self.question)
- if can_ask_anon == False and is_owner:
+ if can_ask_anon is False and is_owner:
self.show_field('reveal_identity')
raise forms.ValidationError(
_(
@@ -938,63 +1111,61 @@ class EditQuestionForm(forms.Form, FormWithHideableFields):
field edit_anonymously. It relies on correct cleaning
if the "reveal_identity" field
"""
+ super(EditQuestionForm, self).clean()
reveal_identity = self.cleaned_data.get('reveal_identity', False)
stay_anonymous = False
- if reveal_identity == False and self.can_stay_anonymous():
+ if reveal_identity is False and self.can_stay_anonymous():
stay_anonymous = True
self.cleaned_data['stay_anonymous'] = stay_anonymous
return self.cleaned_data
-class EditAnswerForm(forms.Form):
+
+class EditAnswerForm(PostAsSomeoneForm):
text = AnswerEditorField()
summary = SummaryField()
wiki = WikiField()
- user = forms.CharField(
- required=False,
- max_length=255,
- label="User",
- help_text=_("Enter the username to post this as. New users are automatically created."),
- widget=forms.TextInput(attrs={'size' : 35}))
def __init__(self, answer, revision, *args, **kwargs):
super(EditAnswerForm, self).__init__(*args, **kwargs)
self.fields['text'].initial = revision.text
self.fields['wiki'].initial = answer.wiki
+
class EditTagWikiForm(forms.Form):
- text = forms.CharField(required = False)
+ text = forms.CharField(required=False)
tag_id = forms.IntegerField()
+
class EditUserForm(forms.Form):
email = forms.EmailField(
label=u'Email',
required=True,
max_length=255,
- widget=forms.TextInput(attrs={'size' : 35})
+ widget=forms.TextInput(attrs={'size': 35})
)
realname = forms.CharField(
label=_('Real name'),
required=False,
max_length=255,
- widget=forms.TextInput(attrs={'size' : 35})
+ widget=forms.TextInput(attrs={'size': 35})
)
website = forms.URLField(
label=_('Website'),
required=False,
max_length=255,
- widget=forms.TextInput(attrs={'size' : 35})
+ widget=forms.TextInput(attrs={'size': 35})
)
city = forms.CharField(
label=_('City'),
required=False,
max_length=255,
- widget=forms.TextInput(attrs={'size' : 35})
+ widget=forms.TextInput(attrs={'size': 35})
)
- country = CountryField(required = False)
+ country = CountryField(required=False)
show_country = forms.BooleanField(
label=_('Show country'),
@@ -1008,15 +1179,18 @@ class EditUserForm(forms.Form):
birthday = forms.DateField(
label=_('Date of birth'),
- help_text=_('will not be shown, used to calculate age, format: YYYY-MM-DD'),
+ help_text=_(
+ 'will not be shown, used to calculate '
+ 'age, format: YYYY-MM-DD'
+ ),
required=False,
- widget=forms.TextInput(attrs={'size' : 35})
+ widget=forms.TextInput(attrs={'size': 35})
)
about = forms.CharField(
label=_('Profile'),
required=False,
- widget=forms.Textarea(attrs={'cols' : 60})
+ widget=forms.Textarea(attrs={'cols': 60})
)
def __init__(self, user, *args, **kwargs):
@@ -1030,7 +1204,7 @@ class EditUserForm(forms.Form):
self.fields['realname'].initial = user.real_name
self.fields['website'].initial = user.website
self.fields['city'].initial = user.location
- if user.country == None:
+ if user.country is None:
country = 'unknown'
else:
country = user.country
@@ -1048,24 +1222,32 @@ class EditUserForm(forms.Form):
"""For security reason one unique email in database"""
if self.user.email != self.cleaned_data['email']:
#todo dry it, there is a similar thing in openidauth
- if askbot_settings.EMAIL_UNIQUE == True:
+ if askbot_settings.EMAIL_UNIQUE is True:
if 'email' in self.cleaned_data:
try:
- User.objects.get(email = self.cleaned_data['email'])
+ User.objects.get(email=self.cleaned_data['email'])
except User.DoesNotExist:
return self.cleaned_data['email']
except User.MultipleObjectsReturned:
- raise forms.ValidationError(_('this email has already been registered, please use another one'))
- raise forms.ValidationError(_('this email has already been registered, please use another one'))
+ raise forms.ValidationError(_(
+ 'this email has already been registered, '
+ 'please use another one')
+ )
+ raise forms.ValidationError(_(
+ 'this email has already been registered, '
+ 'please use another one')
+ )
return self.cleaned_data['email']
+
class TagFilterSelectionForm(forms.ModelForm):
email_tag_filter_strategy = forms.ChoiceField(
- choices = const.TAG_DISPLAY_FILTER_STRATEGY_CHOICES,
- initial = const.EXCLUDE_IGNORED,
- label = _('Choose email tag filter'),
- widget = forms.RadioSelect
+ choices=const.TAG_DISPLAY_FILTER_STRATEGY_CHOICES,
+ initial=const.EXCLUDE_IGNORED,
+ label=_('Choose email tag filter'),
+ widget=forms.RadioSelect
)
+
class Meta:
model = User
fields = ('email_tag_filter_strategy',)
@@ -1082,31 +1264,31 @@ class TagFilterSelectionForm(forms.ModelForm):
class EmailFeedSettingField(forms.ChoiceField):
def __init__(self, *arg, **kwarg):
kwarg['choices'] = const.NOTIFICATION_DELIVERY_SCHEDULE_CHOICES
- #kwarg['initial'] = askbot_settings.DEFAULT_NOTIFICATION_DELIVERY_SCHEDULE
kwarg['widget'] = forms.RadioSelect
super(EmailFeedSettingField, self).__init__(*arg, **kwarg)
+
class EditUserEmailFeedsForm(forms.Form):
FORM_TO_MODEL_MAP = {
- 'all_questions':'q_all',
- 'asked_by_me':'q_ask',
- 'answered_by_me':'q_ans',
- 'individually_selected':'q_sel',
- 'mentions_and_comments':'m_and_c',
+ 'all_questions': 'q_all',
+ 'asked_by_me': 'q_ask',
+ 'answered_by_me': 'q_ans',
+ 'individually_selected': 'q_sel',
+ 'mentions_and_comments': 'm_and_c',
}
NO_EMAIL_INITIAL = {
- 'all_questions':'n',
- 'asked_by_me':'n',
- 'answered_by_me':'n',
- 'individually_selected':'n',
- 'mentions_and_comments':'n',
+ 'all_questions': 'n',
+ 'asked_by_me': 'n',
+ 'answered_by_me': 'n',
+ 'individually_selected': 'n',
+ 'mentions_and_comments': 'n',
}
INSTANT_EMAIL_INITIAL = {
- 'all_questions':'i',
- 'asked_by_me':'i',
- 'answered_by_me':'i',
- 'individually_selected':'i',
- 'mentions_and_comments':'i',
+ 'all_questions': 'i',
+ 'asked_by_me': 'i',
+ 'answered_by_me': 'i',
+ 'individually_selected': 'i',
+ 'mentions_and_comments': 'i',
}
asked_by_me = EmailFeedSettingField(
@@ -1129,7 +1311,7 @@ class EditUserEmailFeedsForm(forms.Form):
def set_initial_values(self, user=None):
from askbot import models
KEY_MAP = dict([(v, k) for k, v in self.FORM_TO_MODEL_MAP.iteritems()])
- if user != None:
+ if user is not None:
settings = models.EmailFeedSetting.objects.filter(subscriber=user)
initial_values = {}
for setting in settings:
@@ -1159,7 +1341,7 @@ class EditUserEmailFeedsForm(forms.Form):
"""
return self.FORM_TO_MODEL_MAP.values()
- def set_frequency(self, frequency = 'n'):
+ def set_frequency(self, frequency='n'):
data = {
'all_questions': frequency,
'asked_by_me': frequency,
@@ -1171,9 +1353,9 @@ class EditUserEmailFeedsForm(forms.Form):
self.cleaned_data = data
self.initial = data
- def save(self,user,save_unbound=False):
- """
- with save_unbound==True will bypass form validation and save initial values
+ def save(self, user, save_unbound=False):
+ """with save_unbound==True will bypass form
+ validation and save initial values
"""
from askbot import models
changed = False
@@ -1201,23 +1383,25 @@ class EditUserEmailFeedsForm(forms.Form):
user.followed_threads.clear()
return changed
+
class SubscribeForEmailUpdatesField(forms.ChoiceField):
"""a simple yes or no field to subscribe for email or not"""
def __init__(self, **kwargs):
kwargs['widget'] = forms.widgets.RadioSelect
kwargs['error_messages'] = {
- 'required':_('please choose one of the options above')
+ 'required': _('please choose one of the options above')
}
kwargs['choices'] = (
- ('y',_('okay, let\'s try!')),
+ ('y', _('okay, let\'s try!')),
(
'n',
- _('no %(sitename)s email please, thanks') \
+ _('no %(sitename)s email please, thanks')
% {'sitename': askbot_settings.APP_SHORT_NAME}
)
)
super(SubscribeForEmailUpdatesField, self).__init__(**kwargs)
+
class SimpleEmailSubscribeForm(forms.Form):
subscribe = SubscribeForEmailUpdatesField()
@@ -1233,11 +1417,13 @@ class SimpleEmailSubscribeForm(forms.Form):
email_settings_form = EFF(initial=EFF.NO_EMAIL_INITIAL)
email_settings_form.save(user, save_unbound=True)
+
class GroupLogoURLForm(forms.Form):
"""form for saving group logo url"""
group_id = forms.IntegerField()
image_url = forms.CharField()
+
class EditGroupMembershipForm(forms.Form):
"""a form for adding or removing users
to and from user groups"""
@@ -1253,11 +1439,12 @@ class EditGroupMembershipForm(forms.Form):
raise forms.ValidationError('invalid action')
return action
+
class EditRejectReasonForm(forms.Form):
- reason_id = forms.IntegerField(required = False)
+ reason_id = forms.IntegerField(required=False)
title = CountedWordsField(
- min_words = 1, max_words = 4, field_name = _('Title')
+ min_words=1, max_words=4, field_name=_('Title')
)
details = CountedWordsField(
- min_words = 6, field_name = _('Description')
+ min_words=6, field_name=_('Description')
)