summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorEvgeny Fadeev <evgeny.fadeev@gmail.com>2012-07-21 21:21:27 -0400
committerEvgeny Fadeev <evgeny.fadeev@gmail.com>2012-07-21 21:21:27 -0400
commit347a178cd35781b9b4110558184f2f30e792a7e6 (patch)
tree3217d99671978868dc8f232351a740e692fcc46b
parent37c7d7d829f75e4982e997f36cc2362ef09d1dcf (diff)
parent54150a2c7c8609ad6f39d31dfc69b03da523eba7 (diff)
downloadaskbot-347a178cd35781b9b4110558184f2f30e792a7e6.tar.gz
askbot-347a178cd35781b9b4110558184f2f30e792a7e6.tar.bz2
askbot-347a178cd35781b9b4110558184f2f30e792a7e6.zip
merged with the master branch
-rw-r--r--askbot/__init__.py12
-rw-r--r--askbot/forms.py517
2 files changed, 335 insertions, 194 deletions
diff --git a/askbot/__init__.py b/askbot/__init__.py
index 859b2695..8e4f20ab 100644
--- a/askbot/__init__.py
+++ b/askbot/__init__.py
@@ -5,9 +5,6 @@ Functions in the askbot module perform various
basic actions on behalf of the forum application
"""
import os
-import smtplib
-import sys
-import logging
VERSION = (0, 7, 43)
@@ -43,17 +40,19 @@ try:
from askbot.deployment.assertions import assert_package_compatibility
assert_package_compatibility()
patches.patch_django()
- patches.patch_coffin()#must go after django
+ patches.patch_coffin() # must go after django
except ImportError:
pass
+
def get_install_directory():
"""returns path to directory
- where code of the askbot django application
+ where code of the askbot django application
is installed
"""
return os.path.dirname(__file__)
+
def get_path_to(relative_path):
"""returns absolute path to a file
relative to ``askbot`` directory
@@ -72,10 +71,11 @@ def get_version():
"""
return '.'.join([str(subversion) for subversion in VERSION])
+
def get_database_engine_name():
"""returns name of the database engine,
independently of the version of django
- - for django >=1.2 looks into ``settings.DATABASES['default']``,
+ - for django >=1.2 looks into ``settings.DATABASES['default']``,
(i.e. assumes that askbot uses database named 'default')
, and for django 1.1 and below returns settings.DATABASE_ENGINE
"""
diff --git a/askbot/forms.py b/askbot/forms.py
index cc11da23..9fc66f45 100644
--- a/askbot/forms.py
+++ b/askbot/forms.py
@@ -1,3 +1,5 @@
+"""Forms, custom form fields and related utility functions
+used in AskBot"""
import re
from django import forms
from askbot import const
@@ -6,7 +8,6 @@ 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
@@ -14,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
@@ -21,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
@@ -36,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()
@@ -54,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
@@ -74,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"""
@@ -101,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
@@ -145,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:
@@ -193,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 = ''
@@ -219,24 +285,33 @@ 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
+
def clean_tag(tag_name):
"""a function that cleans a single tag name"""
tag_length = len(tag_name)
@@ -248,7 +323,7 @@ def clean_tag(tag_name):
'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}
+ ) % {'max_chars': tag_length}
raise forms.ValidationError(msg)
#todo - this needs to come from settings
@@ -264,19 +339,21 @@ def clean_tag(tag_name):
else:
try:
from askbot import models
- stored_tag = models.Tag.objects.get(name__iexact = tag_name)
+ stored_tag = models.Tag.objects.get(name__iexact=tag_name)
return stored_tag.name
except models.Tag.DoesNotExist:
return tag_name
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'}
- )
+ attrs={'size': 50, 'autocomplete': 'off'}
+ )
self.max_length = 255
self.label = _('tags')
self.help_text = ungettext_lazy(
@@ -288,41 +365,18 @@ 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
- num_mandatory_tags = len(models.tag.get_mandatory_tags())
- return askbot_settings.TAGS_ARE_REQUIRED and num_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(
- _(message_keys.TAGS_ARE_REQUIRED_MESSAGE)
- )
+ raise forms.ValidationError(
+ _(message_keys.TAGS_ARE_REQUIRED_MESSAGE)
+ )
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 = []
@@ -332,11 +386,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())}
@@ -350,30 +404,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):
@@ -383,6 +461,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
@@ -390,10 +469,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)
@@ -437,6 +516,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.
@@ -446,13 +526,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']
@@ -486,9 +568,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):
@@ -509,12 +589,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
@@ -562,41 +642,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:"),
@@ -613,20 +691,22 @@ 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(forms.Form):
+
+class FormWithHideableFields(object):
"""allows to swap a field widget to HiddenInput() and back"""
def hide_field(self, name):
@@ -647,7 +727,8 @@ class FormWithHideableFields(forms.Form):
if name in self.__hidden_fields:
self.fields[name] = self.__hidden_fields.pop(name)
-class PostPrivatelyForm(FormWithHideableFields):
+
+class PostPrivatelyForm(forms.Form, FormWithHideableFields):
"""has a single field `post_privately` with
two related methods"""
@@ -683,34 +764,42 @@ class AskForm(PostPrivatelyForm):
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()
group_id = forms.IntegerField(required = False, widget = forms.HiddenInput)
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,
+ 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,
+ 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'}))
- user = forms.CharField(required=False, max_length=255, widget=forms.TextInput(attrs={'size' : 35}))
- email = forms.CharField(required=False, max_length=255, widget=forms.TextInput(attrs={'size' : 35}))
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']
@@ -720,6 +809,7 @@ ASK_BY_EMAIL_SUBJECT_HELP = _(
'[tag1, tag2, tag3,...] question title'
)
+
class AskByEmailForm(forms.Form):
""":class:`~askbot.forms.AskByEmailForm`
validates question data, where question was posted
@@ -738,12 +828,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
}
)
@@ -775,17 +866,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)
@@ -797,22 +890,36 @@ class AskByEmailForm(forms.Form):
raise forms.ValidationError(ASK_BY_EMAIL_SUBJECT_HELP)
return self.cleaned_data['subject']
+
class AnswerForm(PostPrivatelyForm):
- 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, 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)
+ 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,
+ 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)
+
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']
@@ -822,7 +929,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']
@@ -830,43 +939,57 @@ 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(PostPrivatelyForm):
- title = TitleField()
- text = QuestionEditorField()
- tags = TagNamesField()
+ 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,
+ label=_('reveal identity'),
+ required=False,
)
#todo: this is odd that this form takes question as an argument
@@ -896,8 +1019,8 @@ class EditQuestionForm(PostPrivatelyForm):
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)
)
@@ -923,7 +1046,7 @@ class EditQuestionForm(PostPrivatelyForm):
"""
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
@@ -941,7 +1064,7 @@ class EditQuestionForm(PostPrivatelyForm):
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(
_(
@@ -965,11 +1088,12 @@ class EditQuestionForm(PostPrivatelyForm):
"""
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(PostPrivatelyForm):
text = AnswerEditorField()
summary = SummaryField()
@@ -993,39 +1117,40 @@ class EditAnswerForm(PostPrivatelyForm):
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'),
@@ -1039,15 +1164,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):
@@ -1061,7 +1189,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
@@ -1079,24 +1207,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',)
@@ -1113,31 +1249,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(
@@ -1160,7 +1296,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:
@@ -1190,7 +1326,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,
@@ -1202,9 +1338,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
@@ -1232,23 +1368,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()
@@ -1264,11 +1402,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"""
@@ -1284,13 +1424,14 @@ 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')
)
class ModerateTagForm(forms.Form):