diff options
120 files changed, 6816 insertions, 513 deletions
@@ -2,6 +2,8 @@ This is Askbot project - open source Q&A system Demo site is http://askbot.org/meta +All documentation is in the directory forum/documentation + askbot-devel repository is open to anyone who wants to help develop Askbot - just drop us a note Askbot is based on code of CNPROG, originally created by Mike Chen and Sailing Cai and some code written for OSQA diff --git a/django_authopenid/views.py b/django_authopenid/views.py index 3c794a0d..4f7d3efa 100755 --- a/django_authopenid/views.py +++ b/django_authopenid/views.py @@ -71,6 +71,7 @@ from forum.utils.forms import get_next_url EXTERNAL_LOGIN_APP = settings.LOAD_EXTERNAL_LOGIN_APP() +#todo: decouple from forum def login(request,user): from django.contrib.auth import login as _login from forum.models import user_logged_in #custom signal @@ -80,14 +81,27 @@ def login(request,user): #1) get old session key session_key = request.session.session_key - #2) login and get new session key + #2) get old search state + search_state = None + if 'search_state' in request.session: + search_state = request.session['search_state'] + + #3) login and get new session key _login(request,user) - #3) send signal with old session key as argument + #4) transfer search_state to new session if found + if search_state: + search_state.set_logged_in() + request.session['search_state'] = search_state + #5) send signal with old session key as argument logging.debug('logged in user %s with session key %s' % (user.username, session_key)) user_logged_in.send(user=user,session_key=session_key,sender=None) +#todo: uncouple this from forum def logout(request): from django.contrib.auth import logout as _logout#for login I've added wrapper below - called login + if 'search_state' in request.session: + request.session['search_state'].set_logged_out() + request.session.modified = True _logout(request) if settings.USE_EXTERNAL_LEGACY_LOGIN == True: EXTERNAL_LOGIN_APP.api.logout(request) diff --git a/forum/const.py b/forum/const.py index 4c107572..bc9a7a8f 100755 --- a/forum/const.py +++ b/forum/const.py @@ -32,6 +32,46 @@ TYPE_REPUTATION = ( (-8, 'lose_by_upvote_canceled'), ) +#do not translate these!!! +POST_SORT_METHODS = ( + ('latest', _('newest')), + ('oldest', _('oldest')), + ('active', _('active')), + ('inactive', _('inactive')), + ('hottest', _('hottest')), + ('coldest', _('coldest')), + ('mostvoted', _('most voted')), + ('leastvoted', _('least voted')), + ('relevant', _('relevance')), + ) +#todo: add assertion here that all sort methods are unique +#because they are keys to the hash used in implementations of Q.run_advanced_search + +DEFAULT_POST_SORT_METHOD = 'active' +POST_SCOPE_LIST = ( + ('all', _('all')), + ('unanswered', _('unanswered')), + ('favorite', _('favorite')), + ) +DEFAULT_POST_SCOPE = 'all' +DEFAULT_QUESTIONS_PAGE_SIZE = 30 +PAGE_SIZES = (10,30,50) + +UNANSWERED_MEANING_LIST = ('NO_ANSWERS','NO_UPVOTED_ANSWERS','NO_ACCEPTED_ANSWERS') +UNANSWERED_MEANING = 'NO_ACCEPTED_ANSWERS' +assert(UNANSWERED_MEANING in UNANSWERED_MEANING_LIST) + +#todo: +#this probably needs to be language-specific +#and selectable/changeable from the admin interface +#however it will be hard to expect that people will type +#correct regexes - plus this must be an anchored regex +#to do full string match +TAG_REGEX = r'^[a-z0-9\+\.\-]+$' +TAG_SPLIT_REGEX = r'[ ,]+' +MAX_TAG_LENGTH = 20 #default 20 chars +MAX_TAGS_PER_POST = 5 #no more than five tags + TYPE_ACTIVITY_ASK_QUESTION=1 TYPE_ACTIVITY_ANSWER=2 TYPE_ACTIVITY_COMMENT_QUESTION=3 @@ -91,3 +131,4 @@ CONST = { #how to filter questions by tags in email digests? TAG_EMAIL_FILTER_CHOICES = (('ignored', _('exclude ignored tags')),('interesting',_('allow only selected tags'))) MAX_ALERTS_PER_EMAIL = 7 +USERS_PAGE_SIZE = 28 diff --git a/cron/README b/forum/cron/README index d5573150..d5573150 100644 --- a/cron/README +++ b/forum/cron/README diff --git a/cron/multi_award_badges b/forum/cron/multi_award_badges index 3d768772..3d768772 100755 --- a/cron/multi_award_badges +++ b/forum/cron/multi_award_badges diff --git a/cron/multi_award_badges_virtualenv b/forum/cron/multi_award_badges_virtualenv index 4230fb22..4230fb22 100755 --- a/cron/multi_award_badges_virtualenv +++ b/forum/cron/multi_award_badges_virtualenv diff --git a/cron/once_award_badges b/forum/cron/once_award_badges index 069656ca..069656ca 100755 --- a/cron/once_award_badges +++ b/forum/cron/once_award_badges diff --git a/cron/once_award_badges_virtualenv b/forum/cron/once_award_badges_virtualenv index 0011981c..0011981c 100755 --- a/cron/once_award_badges_virtualenv +++ b/forum/cron/once_award_badges_virtualenv diff --git a/cron/send_email_alerts b/forum/cron/send_email_alerts index 7581a88c..7581a88c 100644 --- a/cron/send_email_alerts +++ b/forum/cron/send_email_alerts diff --git a/cron/send_email_alerts_virtualenv b/forum/cron/send_email_alerts_virtualenv index 2f1b64d0..2f1b64d0 100644 --- a/cron/send_email_alerts_virtualenv +++ b/forum/cron/send_email_alerts_virtualenv diff --git a/HOW_TO_DEBUG b/forum/documentation/HOW_TO_DEBUG index fbbdb1f7..fbbdb1f7 100644 --- a/HOW_TO_DEBUG +++ b/forum/documentation/HOW_TO_DEBUG diff --git a/INSTALL b/forum/documentation/INSTALL index 1eb9607c..73714566 100644 --- a/INSTALL +++ b/forum/documentation/INSTALL @@ -74,6 +74,10 @@ and is significantly modified. http://code.google.com/p/django-authopenid/ no need to install this library B. INSTALLATION + +NOTE: If you want to upgrade software, not install from scratch - + take a look into forum/documentation/UPGRADE + ----------------------------------------------- 0. Make sure you have all above python libraries installed. @@ -108,9 +112,13 @@ DATABASE_PASSWORD DATABASE_ENGINE If you set these up, and your database is ready (see section 2), -run: +run (note that application 'forum' is under control of south migration system: + +python manage.py syncdb #create tables for anything not under control of migration system +python manage.py migrate forum #run migration command - will apply all migrations in sequence + +Now you are ready to test your installation: -python manage.py syncdb python manage.py runserver `hostname -i`:8000 (choose another port number if you wish) @@ -121,10 +129,19 @@ please post them at http://askbot.org/meta Prepare your database by using the same database/account configuration from above. -e.g, + +If your host has database manager in the control panel - you +can use that or you can create database by typing commands manually + +on MySQL the commands are: + create database askbot DEFAULT CHARACTER SET UTF8 COLLATE utf8_general_ci; grant all on askbot.* to 'askbot'@'localhost'; -And then run "python manage.py syncdb" to synchronize your database. + +And then run : + +python manage.py syncdb +python manage.py migrate 3. Running Askbot on the development server @@ -241,10 +258,10 @@ WSGIPythonEggs /var/python/eggs #must be readable and writable by apache This function at the moment requires Django 1.1 - edit paths in the file cron/send_email_alerts - set up a cron job to call cron/send_email_alerts once or twice a day + edit paths in the file forum/cron/send_email_alerts + set up a cron job to call forum/cron/send_email_alerts once or twice a day subscription sender may be tested manually in shell - by calling cron/send_email_alerts + by calling forum/cron/send_email_alerts 7. Sitemap Sitemap will be available at /<settings_local.FORUM_SCRIPT_ALIAS>sitemap.xml @@ -258,7 +275,7 @@ https://www.google.com/webmasters/tools/ 8. Miscellaneous -There are some demo scripts under sql_scripts folder, +There are some demo scripts under forum/sql_scripts folder, including badges and test accounts for CNProg.com. You don't need them to run your sample. diff --git a/INSTALL.pip b/forum/documentation/INSTALL.pip index 2f817ff8..2f817ff8 100644 --- a/INSTALL.pip +++ b/forum/documentation/INSTALL.pip diff --git a/INSTALL.webfaction b/forum/documentation/INSTALL.webfaction index a449ffe6..a449ffe6 100644 --- a/INSTALL.webfaction +++ b/forum/documentation/INSTALL.webfaction diff --git a/ROADMAP.rst b/forum/documentation/ROADMAP.rst index c79e0ae4..c79e0ae4 100644 --- a/ROADMAP.rst +++ b/forum/documentation/ROADMAP.rst diff --git a/TODO.rst b/forum/documentation/TODO.rst index f202a3f7..f202a3f7 100644 --- a/TODO.rst +++ b/forum/documentation/TODO.rst diff --git a/forum/documentation/UPGRADE b/forum/documentation/UPGRADE new file mode 100644 index 00000000..538b75a0 --- /dev/null +++ b/forum/documentation/UPGRADE @@ -0,0 +1,24 @@ +if you are upgrading this software, then + +* first download the newer version and write it over the old one. + +for the database migrations you will need to use django package called "south" + +Install it (if you don't have it yet) with: + + easy_install South + +* 'south' must already be in the list of INSTALLED_APPS + otherwise you must have downloaded wrong version of Askbot + +if you are using south the very first time, then type: + + python manage.py migrate forum 0001_initial --fake + +otherwise skip above step. + +Finally run + + python manage.py migrate forum --auto + +then all relevant schema and data migrations will be applied diff --git a/WISH_LIST b/forum/documentation/WISH_LIST index 2b53662c..2b53662c 100644 --- a/WISH_LIST +++ b/forum/documentation/WISH_LIST diff --git a/askbot-requirements.txt b/forum/documentation/askbot-requirements.txt index 66a37fbe..66a37fbe 100644 --- a/askbot-requirements.txt +++ b/forum/documentation/askbot-requirements.txt diff --git a/forum/forms.py b/forum/forms.py index e16db2c6..4139abb8 100755 --- a/forum/forms.py +++ b/forum/forms.py @@ -2,8 +2,10 @@ import re from datetime import date from django import forms from models import * -from const import * +from const import * #todo: clean out import * thing +from forum import const from django.utils.translation import ugettext as _ +from django.utils.translation import ungettext from django.contrib.auth.models import User from django.contrib.contenttypes.models import ContentType from forum.utils.forms import NextUrlField, UserNameField, SetPasswordForm @@ -59,22 +61,34 @@ class TagNamesField(forms.CharField): if len(data) < 1: raise forms.ValidationError(_('tags are required')) - split_re = re.compile(r'[ ,]+') - list = split_re.split(data) - list_temp = [] - if len(list) > 5: - raise forms.ValidationError(_('please use 5 tags or less')) - for tag in list: - if len(tag) > 20: - raise forms.ValidationError(_('tags must be shorter than 20 characters')) - #take tag regex from settings - tagname_re = re.compile(r'[a-z0-9\w._#-]+',re.UNICODE) - if not tagname_re.match(tag): - raise forms.ValidationError(_('please use letters, numbers, and characters \'.-_#\'')) - # only keep one same tag - if tag not in list_temp and len(tag.strip()) > 0: - list_temp.append(tag) - return u' '.join(list_temp) + split_re = re.compile(const.TAG_SPLIT_REGEX) + tag_strings = split_re.split(data) + out_tag_list = [] + tag_count = len(tag_strings) + if tag_count > const.MAX_TAGS_PER_POST: + msg = ungettext( + 'please use %(tag_count)d tag or less',#odd but have to use to pluralize + 'please use %(tag_count)d tags or less', + tag_count) % {'tag_count':tag_count} + raise forms.ValidationError(msg) + for tag in tag_strings: + tag_length = len(tag) + if tag_length > const.MAX_TAG_LENGTH: + #singular form is odd in english, but required for pluralization + #in other languages + msg = ungettext('each tag must be shorter than %(max_chars)d character',#odd but added for completeness + 'each tag must be shorter than %(max_shars)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(_('use-these-chars-in-tags')) + #only keep unique tags + if tag not in out_tag_list: + out_tag_list.append(tag) + return u' '.join(out_tag_list) class WikiField(forms.BooleanField): def __init__(self, *args, **kwargs): @@ -113,6 +127,77 @@ class ModerateUserForm(forms.ModelForm): model = User fields = ('is_approved',) +class AdvancedSearchForm(forms.Form): + #nothing must be required in this form + #it is used by the main questions view + scope = forms.ChoiceField(choices=const.POST_SCOPE_LIST, required=False) + sort = forms.ChoiceField(choices=const.POST_SORT_METHODS, required=False) + query = forms.CharField(max_length=256, required=False) + reset_tags = forms.BooleanField(required=False) + reset_author = forms.BooleanField(required=False) + reset_query = forms.BooleanField(required=False) + start_over = forms.BooleanField(required=False) + tags = forms.CharField(max_length=256,required=False) + author = forms.IntegerField(required=False) + page_size = forms.ChoiceField(choices=const.PAGE_SIZES, required=False) + page = forms.IntegerField(required=False) + + def clean_tags(self): + if 'tags' in self.cleaned_data: + tags_input = self.cleaned_data['tags'].strip() + split_re = re.compile(TAG_SPLIT_REGEX) + tag_strings = split_re.split(tags_input) + tagname_re = re.compile(const.TAG_REGEX, re.UNICODE) + out = set() + for s in tag_strings: + if tagname_re.search(s): + out.add(s) + if len(out) > 0: + self.cleaned_data['tags'] = out + else: + self.cleaned_data['tags'] = None + return self.cleaned_data['tags'] + + def clean_query(self): + if 'query' in self.cleaned_data: + q = self.cleaned_data['query'].strip() + if q == '': + q = None + self.cleaned_data['query'] = q + return self.cleaned_data['query'] + + def clean_page_size(self): + if 'page_size' in self.cleaned_data: + if self.cleaned_data['page_size'] == '': + self.cleaned_data['page_size'] = None + return self.cleaned_data['page_size'] + + def clean(self): + #todo rewrite + if self.cleaned_data['scope'] == '': + del self.cleaned_data['scope'] + if self.cleaned_data['tags'] is None: + del self.cleaned_data['tags'] + if self.cleaned_data['sort'] == '': + del self.cleaned_data['sort'] + if self.cleaned_data['query'] == None: + del self.cleaned_data['query'] + if self.cleaned_data['reset_tags'] == False: + del self.cleaned_data['reset_tags'] + if self.cleaned_data['reset_author'] == False: + del self.cleaned_data['reset_author'] + if self.cleaned_data['reset_query'] == False: + del self.cleaned_data['reset_query'] + if self.cleaned_data['start_over'] == False: + del self.cleaned_data['start_over'] + if self.cleaned_data['author'] is None: + del self.cleaned_data['author'] + if self.cleaned_data['page'] is None: + del self.cleaned_data['page'] + if self.cleaned_data['page_size'] is None: + del self.cleaned_data['page_size'] + return self.cleaned_data + class NotARobotForm(forms.Form): recaptcha = ReCaptchaField() diff --git a/stackexchange/__init__.py b/forum/importers/__init__.py index e69de29b..e69de29b 100644 --- a/stackexchange/__init__.py +++ b/forum/importers/__init__.py diff --git a/stackexchange/ANOMALIES b/forum/importers/stackexchange/ANOMALIES index 05a7dbdb..05a7dbdb 100644 --- a/stackexchange/ANOMALIES +++ b/forum/importers/stackexchange/ANOMALIES diff --git a/stackexchange/README b/forum/importers/stackexchange/README index 598a8555..598a8555 100644 --- a/stackexchange/README +++ b/forum/importers/stackexchange/README diff --git a/stackexchange/management/__init__.py b/forum/importers/stackexchange/__init__.py index e69de29b..e69de29b 100644 --- a/stackexchange/management/__init__.py +++ b/forum/importers/stackexchange/__init__.py diff --git a/stackexchange/management/commands/__init__.py b/forum/importers/stackexchange/management/__init__.py index e69de29b..e69de29b 100644 --- a/stackexchange/management/commands/__init__.py +++ b/forum/importers/stackexchange/management/__init__.py diff --git a/forum/importers/stackexchange/management/commands/__init__.py b/forum/importers/stackexchange/management/commands/__init__.py new file mode 100644 index 00000000..e69de29b --- /dev/null +++ b/forum/importers/stackexchange/management/commands/__init__.py diff --git a/stackexchange/management/commands/load_stackexchange.py b/forum/importers/stackexchange/management/commands/load_stackexchange.py index 9cfc7192..ee22e33a 100644 --- a/stackexchange/management/commands/load_stackexchange.py +++ b/forum/importers/stackexchange/management/commands/load_stackexchange.py @@ -4,11 +4,11 @@ from django.template.defaultfilters import slugify #todo: adopt unicode-aware sl import os import re import sys -import stackexchange.parse_models as se_parser +import forum.importers.stackexchange.parse_models as se_parser from xml.etree import ElementTree as et from django.db import models import forum.models as askbot -import stackexchange.models as se +import forum.importers.stackexchange.models as se from forum.forms import EditUserEmailFeedsForm from forum.utils.html import sanitize_html from django.conf import settings diff --git a/stackexchange/models.py b/forum/importers/stackexchange/models.py index a30a9859..a30a9859 100644 --- a/stackexchange/models.py +++ b/forum/importers/stackexchange/models.py diff --git a/stackexchange/parse_models.py b/forum/importers/stackexchange/parse_models.py index 64796e57..64796e57 100644 --- a/stackexchange/parse_models.py +++ b/forum/importers/stackexchange/parse_models.py diff --git a/forum/middleware/view_log.py b/forum/middleware/view_log.py new file mode 100644 index 00000000..bf0b9fbb --- /dev/null +++ b/forum/middleware/view_log.py @@ -0,0 +1,74 @@ +import logging +from django.conf import settings +from forum.views.readers import questions as questions_view +from forum.views.commands import vote +from django.views.static import serve +from forum.views.writers import delete_comment, question_comments, answer_comments +from forum.views.readers import question, question_revisions, answer_revisions + +#todo: the list is getting bigger and bigger - maybe there is a better way to +#trigger reset of sarch state? +IGNORED_VIEWS = (serve, vote, delete_comment, + question_comments, answer_comments, + question_revisions, answer_revisions) + +class ViewLog(object): + """must be modified only in this middlware + however, can be read anywhere else + """ + def __init__(self): + self.views = [] + self.depth = 3 #todo maybe move this to const.py + def set_current(self, view_name): + thi + + def get_previous(self, num): + if num > self.depth - 1: + raise Exception("view log depth exceeded") + elif num < 0: + raise Exception("num must be positive"); + elif num <= len(self.views) - 1: + return self.views[num] + else: + return None + + def set_current(self, view_name): + self.views.insert(0, view_name) + if len(self.views) > self.depth: + self.views.pop() + + def __str__(self): + return str(self.views) + ' depth=%d' % self.depth + +class ViewLogMiddleware(object): + def process_view(self, request, view_func, view_args, view_kwargs): + if view_func == questions_view: + view_str = 'questions' + elif view_func in IGNORED_VIEWS: + return + else: + view_str = view_func.__name__ + if view_str == 'wrap': + return + + if settings.DEBUG == True: + #todo: dependency! + from debug_toolbar.views import debug_media as debug_media_view + if view_func == debug_media_view: + return + else: + view_str = view_func.__name__ + + if request.user.is_authenticated(): + user_name = request.user.username + else: + user_name = request.META['REMOTE_ADDR'] + logging.debug('user %s, view %s' % (request.user.username, view_str)) + + if 'view_log' in request.session: + view_log = request.session['view_log'] + else: + view_log = ViewLog() + + view_log.set_current(view_str) + request.session['view_log'] = view_log diff --git a/forum/migrations/0001_initial.py b/forum/migrations/0001_initial.py new file mode 100644 index 00000000..e6350446 --- /dev/null +++ b/forum/migrations/0001_initial.py @@ -0,0 +1,780 @@ +# encoding: 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 'Vote' + db.create_table(u'vote', ( + ('object_id', self.gf('django.db.models.fields.PositiveIntegerField')()), + ('voted_at', self.gf('django.db.models.fields.DateTimeField')(default=datetime.datetime.now)), + ('user', self.gf('django.db.models.fields.related.ForeignKey')(related_name='votes', to=orm['auth.User'])), + ('content_type', self.gf('django.db.models.fields.related.ForeignKey')(to=orm['contenttypes.ContentType'])), + ('vote', self.gf('django.db.models.fields.SmallIntegerField')()), + ('id', self.gf('django.db.models.fields.AutoField')(primary_key=True)), + )) + db.send_create_signal('forum', ['Vote']) + + # Adding unique constraint on 'Vote', fields ['content_type', 'object_id', 'user'] + db.create_unique(u'vote', ['content_type_id', 'object_id', 'user_id']) + + # Adding model 'FlaggedItem' + db.create_table(u'flagged_item', ( + ('object_id', self.gf('django.db.models.fields.PositiveIntegerField')()), + ('flagged_at', self.gf('django.db.models.fields.DateTimeField')(default=datetime.datetime.now)), + ('id', self.gf('django.db.models.fields.AutoField')(primary_key=True)), + ('content_type', self.gf('django.db.models.fields.related.ForeignKey')(to=orm['contenttypes.ContentType'])), + ('user', self.gf('django.db.models.fields.related.ForeignKey')(related_name='flaggeditems', to=orm['auth.User'])), + )) + db.send_create_signal('forum', ['FlaggedItem']) + + # Adding unique constraint on 'FlaggedItem', fields ['content_type', 'object_id', 'user'] + db.create_unique(u'flagged_item', ['content_type_id', 'object_id', 'user_id']) + + # Adding model 'Comment' + db.create_table(u'comment', ( + ('comment', self.gf('django.db.models.fields.CharField')(max_length=300)), + ('object_id', self.gf('django.db.models.fields.PositiveIntegerField')()), + ('added_at', self.gf('django.db.models.fields.DateTimeField')(default=datetime.datetime.now)), + ('content_type', self.gf('django.db.models.fields.related.ForeignKey')(to=orm['contenttypes.ContentType'])), + ('id', self.gf('django.db.models.fields.AutoField')(primary_key=True)), + ('user', self.gf('django.db.models.fields.related.ForeignKey')(related_name='comments', to=orm['auth.User'])), + )) + db.send_create_signal('forum', ['Comment']) + + # Adding model 'Tag' + db.create_table(u'tag', ( + ('name', self.gf('django.db.models.fields.CharField')(unique=True, max_length=255)), + ('deleted', self.gf('django.db.models.fields.BooleanField')(default=False, blank=True)), + ('created_by', self.gf('django.db.models.fields.related.ForeignKey')(related_name='created_tags', to=orm['auth.User'])), + ('deleted_by', self.gf('django.db.models.fields.related.ForeignKey')(blank=True, related_name='deleted_tags', null=True, to=orm['auth.User'])), + ('used_count', self.gf('django.db.models.fields.PositiveIntegerField')(default=0)), + ('deleted_at', self.gf('django.db.models.fields.DateTimeField')(null=True, blank=True)), + ('id', self.gf('django.db.models.fields.AutoField')(primary_key=True)), + )) + db.send_create_signal('forum', ['Tag']) + + # Adding model 'MarkedTag' + db.create_table('forum_markedtag', ( + ('reason', self.gf('django.db.models.fields.CharField')(max_length=16)), + ('tag', self.gf('django.db.models.fields.related.ForeignKey')(related_name='user_selections', to=orm['forum.Tag'])), + ('id', self.gf('django.db.models.fields.AutoField')(primary_key=True)), + ('user', self.gf('django.db.models.fields.related.ForeignKey')(related_name='tag_selections', to=orm['auth.User'])), + )) + db.send_create_signal('forum', ['MarkedTag']) + + # Adding model 'Question' + db.create_table(u'question', ( + ('wiki', self.gf('django.db.models.fields.BooleanField')(default=False, blank=True)), + ('vote_up_count', self.gf('django.db.models.fields.IntegerField')(default=0)), + ('answer_accepted', self.gf('django.db.models.fields.BooleanField')(default=False, blank=True)), + ('offensive_flag_count', self.gf('django.db.models.fields.SmallIntegerField')(default=0)), + ('closed_at', self.gf('django.db.models.fields.DateTimeField')(null=True, blank=True)), + ('deleted_at', self.gf('django.db.models.fields.DateTimeField')(null=True, blank=True)), + ('id', self.gf('django.db.models.fields.AutoField')(primary_key=True)), + ('last_activity_by', self.gf('django.db.models.fields.related.ForeignKey')(related_name='last_active_in_questions', to=orm['auth.User'])), + ('view_count', self.gf('django.db.models.fields.PositiveIntegerField')(default=0)), + ('locked_at', self.gf('django.db.models.fields.DateTimeField')(null=True, blank=True)), + ('score', self.gf('django.db.models.fields.IntegerField')(default=0)), + ('author', self.gf('django.db.models.fields.related.ForeignKey')(related_name='questions', to=orm['auth.User'])), + ('comment_count', self.gf('django.db.models.fields.PositiveIntegerField')(default=0)), + ('html', self.gf('django.db.models.fields.TextField')()), + ('vote_down_count', self.gf('django.db.models.fields.IntegerField')(default=0)), + ('closed', self.gf('django.db.models.fields.BooleanField')(default=False, blank=True)), + ('last_edited_by', self.gf('django.db.models.fields.related.ForeignKey')(blank=True, related_name='last_edited_questions', null=True, to=orm['auth.User'])), + ('favourite_count', self.gf('django.db.models.fields.PositiveIntegerField')(default=0)), + ('deleted', self.gf('django.db.models.fields.BooleanField')(default=False, blank=True)), + ('summary', self.gf('django.db.models.fields.CharField')(max_length=180)), + ('answer_count', self.gf('django.db.models.fields.PositiveIntegerField')(default=0)), + ('last_activity_at', self.gf('django.db.models.fields.DateTimeField')(default=datetime.datetime.now)), + ('closed_by', self.gf('django.db.models.fields.related.ForeignKey')(blank=True, related_name='closed_questions', null=True, to=orm['auth.User'])), + ('close_reason', self.gf('django.db.models.fields.SmallIntegerField')(null=True, blank=True)), + ('locked', self.gf('django.db.models.fields.BooleanField')(default=False, blank=True)), + ('tagnames', self.gf('django.db.models.fields.CharField')(max_length=125)), + ('locked_by', self.gf('django.db.models.fields.related.ForeignKey')(blank=True, related_name='locked_questions', null=True, to=orm['auth.User'])), + ('added_at', self.gf('django.db.models.fields.DateTimeField')(default=datetime.datetime.now)), + ('deleted_by', self.gf('django.db.models.fields.related.ForeignKey')(blank=True, related_name='deleted_questions', null=True, to=orm['auth.User'])), + ('wikified_at', self.gf('django.db.models.fields.DateTimeField')(null=True, blank=True)), + ('title', self.gf('django.db.models.fields.CharField')(max_length=300)), + ('last_edited_at', self.gf('django.db.models.fields.DateTimeField')(null=True, blank=True)), + )) + db.send_create_signal('forum', ['Question']) + + # Adding M2M table for field followed_by on 'Question' + db.create_table(u'question_followed_by', ( + ('id', models.AutoField(verbose_name='ID', primary_key=True, auto_created=True)), + ('question', models.ForeignKey(orm['forum.question'], null=False)), + ('user', models.ForeignKey(orm['auth.user'], null=False)) + )) + db.create_unique(u'question_followed_by', ['question_id', 'user_id']) + + # Adding M2M table for field tags on 'Question' + db.create_table(u'question_tags', ( + ('id', models.AutoField(verbose_name='ID', primary_key=True, auto_created=True)), + ('question', models.ForeignKey(orm['forum.question'], null=False)), + ('tag', models.ForeignKey(orm['forum.tag'], null=False)) + )) + db.create_unique(u'question_tags', ['question_id', 'tag_id']) + + # Adding model 'QuestionView' + db.create_table('forum_questionview', ( + ('when', self.gf('django.db.models.fields.DateTimeField')()), + ('who', self.gf('django.db.models.fields.related.ForeignKey')(related_name='question_views', to=orm['auth.User'])), + ('question', self.gf('django.db.models.fields.related.ForeignKey')(related_name='viewed', to=orm['forum.Question'])), + ('id', self.gf('django.db.models.fields.AutoField')(primary_key=True)), + )) + db.send_create_signal('forum', ['QuestionView']) + + # Adding model 'FavoriteQuestion' + db.create_table(u'favorite_question', ( + ('question', self.gf('django.db.models.fields.related.ForeignKey')(to=orm['forum.Question'])), + ('id', self.gf('django.db.models.fields.AutoField')(primary_key=True)), + ('added_at', self.gf('django.db.models.fields.DateTimeField')(default=datetime.datetime.now)), + ('user', self.gf('django.db.models.fields.related.ForeignKey')(related_name='user_favorite_questions', to=orm['auth.User'])), + )) + db.send_create_signal('forum', ['FavoriteQuestion']) + + # Adding model 'QuestionRevision' + db.create_table(u'question_revision', ( + ('author', self.gf('django.db.models.fields.related.ForeignKey')(related_name='questionrevisions', to=orm['auth.User'])), + ('tagnames', self.gf('django.db.models.fields.CharField')(max_length=125)), + ('text', self.gf('django.db.models.fields.TextField')()), + ('title', self.gf('django.db.models.fields.CharField')(max_length=300)), + ('question', self.gf('django.db.models.fields.related.ForeignKey')(related_name='revisions', to=orm['forum.Question'])), + ('revised_at', self.gf('django.db.models.fields.DateTimeField')()), + ('summary', self.gf('django.db.models.fields.CharField')(max_length=300, blank=True)), + ('id', self.gf('django.db.models.fields.AutoField')(primary_key=True)), + ('revision', self.gf('django.db.models.fields.PositiveIntegerField')()), + )) + db.send_create_signal('forum', ['QuestionRevision']) + + # Adding model 'AnonymousQuestion' + db.create_table('forum_anonymousquestion', ( + ('wiki', self.gf('django.db.models.fields.BooleanField')(default=False, blank=True)), + ('ip_addr', self.gf('django.db.models.fields.IPAddressField')(max_length=15)), + ('author', self.gf('django.db.models.fields.related.ForeignKey')(to=orm['auth.User'], null=True)), + ('tagnames', self.gf('django.db.models.fields.CharField')(max_length=125)), + ('text', self.gf('django.db.models.fields.TextField')()), + ('title', self.gf('django.db.models.fields.CharField')(max_length=300)), + ('added_at', self.gf('django.db.models.fields.DateTimeField')(default=datetime.datetime.now)), + ('summary', self.gf('django.db.models.fields.CharField')(max_length=180)), + ('session_key', self.gf('django.db.models.fields.CharField')(max_length=40)), + ('id', self.gf('django.db.models.fields.AutoField')(primary_key=True)), + )) + db.send_create_signal('forum', ['AnonymousQuestion']) + + # Adding model 'Answer' + db.create_table(u'answer', ( + ('wiki', self.gf('django.db.models.fields.BooleanField')(default=False, blank=True)), + ('vote_up_count', self.gf('django.db.models.fields.IntegerField')(default=0)), + ('offensive_flag_count', self.gf('django.db.models.fields.SmallIntegerField')(default=0)), + ('deleted_at', self.gf('django.db.models.fields.DateTimeField')(null=True, blank=True)), + ('id', self.gf('django.db.models.fields.AutoField')(primary_key=True)), + ('locked_at', self.gf('django.db.models.fields.DateTimeField')(null=True, blank=True)), + ('score', self.gf('django.db.models.fields.IntegerField')(default=0)), + ('author', self.gf('django.db.models.fields.related.ForeignKey')(related_name='answers', to=orm['auth.User'])), + ('question', self.gf('django.db.models.fields.related.ForeignKey')(related_name='answers', to=orm['forum.Question'])), + ('comment_count', self.gf('django.db.models.fields.PositiveIntegerField')(default=0)), + ('html', self.gf('django.db.models.fields.TextField')()), + ('vote_down_count', self.gf('django.db.models.fields.IntegerField')(default=0)), + ('last_edited_by', self.gf('django.db.models.fields.related.ForeignKey')(blank=True, related_name='last_edited_answers', null=True, to=orm['auth.User'])), + ('accepted_at', self.gf('django.db.models.fields.DateTimeField')(null=True, blank=True)), + ('deleted', self.gf('django.db.models.fields.BooleanField')(default=False, blank=True)), + ('accepted', self.gf('django.db.models.fields.BooleanField')(default=False, blank=True)), + ('locked', self.gf('django.db.models.fields.BooleanField')(default=False, blank=True)), + ('locked_by', self.gf('django.db.models.fields.related.ForeignKey')(blank=True, related_name='locked_answers', null=True, to=orm['auth.User'])), + ('added_at', self.gf('django.db.models.fields.DateTimeField')(default=datetime.datetime.now)), + ('deleted_by', self.gf('django.db.models.fields.related.ForeignKey')(blank=True, related_name='deleted_answers', null=True, to=orm['auth.User'])), + ('wikified_at', self.gf('django.db.models.fields.DateTimeField')(null=True, blank=True)), + ('last_edited_at', self.gf('django.db.models.fields.DateTimeField')(null=True, blank=True)), + )) + db.send_create_signal('forum', ['Answer']) + + # Adding model 'AnswerRevision' + db.create_table(u'answer_revision', ( + ('author', self.gf('django.db.models.fields.related.ForeignKey')(related_name='answerrevisions', to=orm['auth.User'])), + ('text', self.gf('django.db.models.fields.TextField')()), + ('revised_at', self.gf('django.db.models.fields.DateTimeField')()), + ('summary', self.gf('django.db.models.fields.CharField')(max_length=300, blank=True)), + ('answer', self.gf('django.db.models.fields.related.ForeignKey')(related_name='revisions', to=orm['forum.Answer'])), + ('id', self.gf('django.db.models.fields.AutoField')(primary_key=True)), + ('revision', self.gf('django.db.models.fields.PositiveIntegerField')()), + )) + db.send_create_signal('forum', ['AnswerRevision']) + + # Adding model 'AnonymousAnswer' + db.create_table('forum_anonymousanswer', ( + ('wiki', self.gf('django.db.models.fields.BooleanField')(default=False, blank=True)), + ('ip_addr', self.gf('django.db.models.fields.IPAddressField')(max_length=15)), + ('author', self.gf('django.db.models.fields.related.ForeignKey')(to=orm['auth.User'], null=True)), + ('text', self.gf('django.db.models.fields.TextField')()), + ('question', self.gf('django.db.models.fields.related.ForeignKey')(related_name='anonymous_answers', to=orm['forum.Question'])), + ('added_at', self.gf('django.db.models.fields.DateTimeField')(default=datetime.datetime.now)), + ('summary', self.gf('django.db.models.fields.CharField')(max_length=180)), + ('session_key', self.gf('django.db.models.fields.CharField')(max_length=40)), + ('id', self.gf('django.db.models.fields.AutoField')(primary_key=True)), + )) + db.send_create_signal('forum', ['AnonymousAnswer']) + + # Adding model 'Activity' + db.create_table(u'activity', ( + ('is_auditted', self.gf('django.db.models.fields.BooleanField')(default=False, blank=True)), + ('object_id', self.gf('django.db.models.fields.PositiveIntegerField')()), + ('user', self.gf('django.db.models.fields.related.ForeignKey')(to=orm['auth.User'])), + ('content_type', self.gf('django.db.models.fields.related.ForeignKey')(to=orm['contenttypes.ContentType'])), + ('active_at', self.gf('django.db.models.fields.DateTimeField')(default=datetime.datetime.now)), + ('id', self.gf('django.db.models.fields.AutoField')(primary_key=True)), + ('activity_type', self.gf('django.db.models.fields.SmallIntegerField')()), + )) + db.send_create_signal('forum', ['Activity']) + + # Adding model 'EmailFeedSetting' + db.create_table('forum_emailfeedsetting', ( + ('reported_at', self.gf('django.db.models.fields.DateTimeField')(null=True)), + ('added_at', self.gf('django.db.models.fields.DateTimeField')(auto_now_add=True, blank=True)), + ('subscriber', self.gf('django.db.models.fields.related.ForeignKey')(to=orm['auth.User'])), + ('feed_type', self.gf('django.db.models.fields.CharField')(max_length=16)), + ('frequency', self.gf('django.db.models.fields.CharField')(default='n', max_length=8)), + ('id', self.gf('django.db.models.fields.AutoField')(primary_key=True)), + )) + db.send_create_signal('forum', ['EmailFeedSetting']) + + # Adding model 'ValidationHash' + db.create_table('forum_validationhash', ( + ('hash_code', self.gf('django.db.models.fields.CharField')(unique=True, max_length=255)), + ('seed', self.gf('django.db.models.fields.CharField')(max_length=12)), + ('expiration', self.gf('django.db.models.fields.DateTimeField')(default=datetime.datetime(2010, 4, 25, 13, 14, 41, 581000))), + ('type', self.gf('django.db.models.fields.CharField')(max_length=12)), + ('id', self.gf('django.db.models.fields.AutoField')(primary_key=True)), + ('user', self.gf('django.db.models.fields.related.ForeignKey')(to=orm['auth.User'])), + )) + db.send_create_signal('forum', ['ValidationHash']) + + # Adding unique constraint on 'ValidationHash', fields ['user', 'type'] + db.create_unique('forum_validationhash', ['user_id', 'type']) + + # Adding model 'AuthKeyUserAssociation' + db.create_table('forum_authkeyuserassociation', ( + ('added_at', self.gf('django.db.models.fields.DateTimeField')(default=datetime.datetime.now)), + ('user', self.gf('django.db.models.fields.related.ForeignKey')(related_name='auth_keys', to=orm['auth.User'])), + ('id', self.gf('django.db.models.fields.AutoField')(primary_key=True)), + ('key', self.gf('django.db.models.fields.CharField')(unique=True, max_length=255)), + ('provider', self.gf('django.db.models.fields.CharField')(max_length=64)), + )) + db.send_create_signal('forum', ['AuthKeyUserAssociation']) + + # Adding model 'Badge' + db.create_table(u'badge', ( + ('multiple', self.gf('django.db.models.fields.BooleanField')(default=False, blank=True)), + ('description', self.gf('django.db.models.fields.CharField')(max_length=300)), + ('id', self.gf('django.db.models.fields.AutoField')(primary_key=True)), + ('awarded_count', self.gf('django.db.models.fields.PositiveIntegerField')(default=0)), + ('type', self.gf('django.db.models.fields.SmallIntegerField')()), + ('slug', self.gf('django.db.models.fields.SlugField')(db_index=True, max_length=50, blank=True)), + ('name', self.gf('django.db.models.fields.CharField')(max_length=50)), + )) + db.send_create_signal('forum', ['Badge']) + + # Adding unique constraint on 'Badge', fields ['name', 'type'] + db.create_unique(u'badge', ['name', 'type']) + + # Adding model 'Award' + db.create_table(u'award', ( + ('awarded_at', self.gf('django.db.models.fields.DateTimeField')(default=datetime.datetime.now)), + ('notified', self.gf('django.db.models.fields.BooleanField')(default=False, blank=True)), + ('object_id', self.gf('django.db.models.fields.PositiveIntegerField')()), + ('user', self.gf('django.db.models.fields.related.ForeignKey')(related_name='award_user', to=orm['auth.User'])), + ('content_type', self.gf('django.db.models.fields.related.ForeignKey')(to=orm['contenttypes.ContentType'])), + ('badge', self.gf('django.db.models.fields.related.ForeignKey')(related_name='award_badge', to=orm['forum.Badge'])), + ('id', self.gf('django.db.models.fields.AutoField')(primary_key=True)), + )) + db.send_create_signal('forum', ['Award']) + + # Adding model 'Repute' + db.create_table(u'repute', ( + ('positive', self.gf('django.db.models.fields.SmallIntegerField')(default=0)), + ('question', self.gf('django.db.models.fields.related.ForeignKey')(to=orm['forum.Question'])), + ('negative', self.gf('django.db.models.fields.SmallIntegerField')(default=0)), + ('reputation_type', self.gf('django.db.models.fields.SmallIntegerField')()), + ('user', self.gf('django.db.models.fields.related.ForeignKey')(to=orm['auth.User'])), + ('reputed_at', self.gf('django.db.models.fields.DateTimeField')(default=datetime.datetime.now)), + ('id', self.gf('django.db.models.fields.AutoField')(primary_key=True)), + ('reputation', self.gf('django.db.models.fields.IntegerField')(default=1)), + )) + db.send_create_signal('forum', ['Repute']) + + # Adding model 'Book' + db.create_table(u'book', ( + ('publication', self.gf('django.db.models.fields.CharField')(max_length=255)), + ('short_name', self.gf('django.db.models.fields.CharField')(max_length=255)), + ('author', self.gf('django.db.models.fields.CharField')(max_length=255)), + ('cover_img', self.gf('django.db.models.fields.CharField')(max_length=255)), + ('price', self.gf('django.db.models.fields.DecimalField')(max_digits=6, decimal_places=2)), + ('title', self.gf('django.db.models.fields.CharField')(max_length=255)), + ('added_at', self.gf('django.db.models.fields.DateTimeField')()), + ('pages', self.gf('django.db.models.fields.SmallIntegerField')()), + ('tagnames', self.gf('django.db.models.fields.CharField')(max_length=125)), + ('published_at', self.gf('django.db.models.fields.DateTimeField')()), + ('user', self.gf('django.db.models.fields.related.ForeignKey')(to=orm['auth.User'])), + ('id', self.gf('django.db.models.fields.AutoField')(primary_key=True)), + ('last_edited_at', self.gf('django.db.models.fields.DateTimeField')()), + )) + db.send_create_signal('forum', ['Book']) + + # Adding M2M table for field questions on 'Book' + db.create_table('book_question', ( + ('id', models.AutoField(verbose_name='ID', primary_key=True, auto_created=True)), + ('book', models.ForeignKey(orm['forum.book'], null=False)), + ('question', models.ForeignKey(orm['forum.question'], null=False)) + )) + db.create_unique('book_question', ['book_id', 'question_id']) + + # Adding model 'BookAuthorInfo' + db.create_table(u'book_author_info', ( + ('added_at', self.gf('django.db.models.fields.DateTimeField')()), + ('book', self.gf('django.db.models.fields.related.ForeignKey')(to=orm['forum.Book'])), + ('user', self.gf('django.db.models.fields.related.ForeignKey')(to=orm['auth.User'])), + ('blog_url', self.gf('django.db.models.fields.CharField')(max_length=255)), + ('id', self.gf('django.db.models.fields.AutoField')(primary_key=True)), + ('last_edited_at', self.gf('django.db.models.fields.DateTimeField')()), + )) + db.send_create_signal('forum', ['BookAuthorInfo']) + + # Adding model 'BookAuthorRss' + db.create_table(u'book_author_rss', ( + ('title', self.gf('django.db.models.fields.CharField')(max_length=255)), + ('url', self.gf('django.db.models.fields.CharField')(max_length=255)), + ('added_at', self.gf('django.db.models.fields.DateTimeField')()), + ('book', self.gf('django.db.models.fields.related.ForeignKey')(to=orm['forum.Book'])), + ('user', self.gf('django.db.models.fields.related.ForeignKey')(to=orm['auth.User'])), + ('rss_created_at', self.gf('django.db.models.fields.DateTimeField')()), + ('id', self.gf('django.db.models.fields.AutoField')(primary_key=True)), + )) + db.send_create_signal('forum', ['BookAuthorRss']) + + + def backwards(self, orm): + + # Deleting model 'Vote' + db.delete_table(u'vote') + + # Removing unique constraint on 'Vote', fields ['content_type', 'object_id', 'user'] + db.delete_unique(u'vote', ['content_type_id', 'object_id', 'user_id']) + + # Deleting model 'FlaggedItem' + db.delete_table(u'flagged_item') + + # Removing unique constraint on 'FlaggedItem', fields ['content_type', 'object_id', 'user'] + db.delete_unique(u'flagged_item', ['content_type_id', 'object_id', 'user_id']) + + # Deleting model 'Comment' + db.delete_table(u'comment') + + # Deleting model 'Tag' + db.delete_table(u'tag') + + # Deleting model 'MarkedTag' + db.delete_table('forum_markedtag') + + # Deleting model 'Question' + db.delete_table(u'question') + + # Removing M2M table for field followed_by on 'Question' + db.delete_table('question_followed_by') + + # Removing M2M table for field tags on 'Question' + db.delete_table('question_tags') + + # Deleting model 'QuestionView' + db.delete_table('forum_questionview') + + # Deleting model 'FavoriteQuestion' + db.delete_table(u'favorite_question') + + # Deleting model 'QuestionRevision' + db.delete_table(u'question_revision') + + # Deleting model 'AnonymousQuestion' + db.delete_table('forum_anonymousquestion') + + # Deleting model 'Answer' + db.delete_table(u'answer') + + # Deleting model 'AnswerRevision' + db.delete_table(u'answer_revision') + + # Deleting model 'AnonymousAnswer' + db.delete_table('forum_anonymousanswer') + + # Deleting model 'Activity' + db.delete_table(u'activity') + + # Deleting model 'EmailFeedSetting' + db.delete_table('forum_emailfeedsetting') + + # Deleting model 'ValidationHash' + db.delete_table('forum_validationhash') + + # Removing unique constraint on 'ValidationHash', fields ['user', 'type'] + db.delete_unique('forum_validationhash', ['user_id', 'type']) + + # Deleting model 'AuthKeyUserAssociation' + db.delete_table('forum_authkeyuserassociation') + + # Deleting model 'Badge' + db.delete_table(u'badge') + + # Removing unique constraint on 'Badge', fields ['name', 'type'] + db.delete_unique(u'badge', ['name', 'type']) + + # Deleting model 'Award' + db.delete_table(u'award') + + # Deleting model 'Repute' + db.delete_table(u'repute') + + # Deleting model 'Book' + db.delete_table(u'book') + + # Removing M2M table for field questions on 'Book' + db.delete_table('book_question') + + # Deleting model 'BookAuthorInfo' + db.delete_table(u'book_author_info') + + # Deleting model 'BookAuthorRss' + db.delete_table(u'book_author_rss') + + + models = { + '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']", 'blank': 'True'}) + }, + 'auth.permission': { + 'Meta': {'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'}), + 'bronze': ('django.db.models.fields.SmallIntegerField', [], {'default': '0'}), + 'date_joined': ('django.db.models.fields.DateTimeField', [], {'default': 'datetime.datetime.now'}), + 'date_of_birth': ('django.db.models.fields.DateField', [], {'null': 'True', 'blank': 'True'}), + 'email': ('django.db.models.fields.EmailField', [], {'max_length': '75', 'blank': 'True'}), + 'email_isvalid': ('django.db.models.fields.BooleanField', [], {'default': 'False', 'blank': 'True'}), + 'email_key': ('django.db.models.fields.CharField', [], {'max_length': '32', 'null': 'True'}), + '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']", 'blank': 'True'}), + 'hide_ignored_questions': ('django.db.models.fields.BooleanField', [], {'default': 'False', 'blank': 'True'}), + 'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}), + 'is_active': ('django.db.models.fields.BooleanField', [], {'default': 'True', 'blank': 'True'}), + 'is_approved': ('django.db.models.fields.BooleanField', [], {'default': 'False', 'blank': 'True'}), + 'is_staff': ('django.db.models.fields.BooleanField', [], {'default': 'False', 'blank': 'True'}), + 'is_superuser': ('django.db.models.fields.BooleanField', [], {'default': 'False', 'blank': 'True'}), + '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'}), + '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'}), + 'silver': ('django.db.models.fields.SmallIntegerField', [], {'default': '0'}), + 'tag_filter_setting': ('django.db.models.fields.CharField', [], {'default': "'ignored'", 'max_length': '16'}), + 'user_permissions': ('django.db.models.fields.related.ManyToManyField', [], {'to': "orm['auth.Permission']", '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': {'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'}) + }, + 'forum.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', 'blank': 'True'}), + 'object_id': ('django.db.models.fields.PositiveIntegerField', [], {}), + 'user': ('django.db.models.fields.related.ForeignKey', [], {'to': "orm['auth.User']"}) + }, + 'forum.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['forum.Question']"}), + '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', 'blank': 'True'}) + }, + 'forum.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'}), + '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', 'blank': 'True'}) + }, + 'forum.answer': { + 'Meta': {'object_name': 'Answer', 'db_table': "u'answer'"}, + 'accepted': ('django.db.models.fields.BooleanField', [], {'default': 'False', 'blank': 'True'}), + 'accepted_at': ('django.db.models.fields.DateTimeField', [], {'null': 'True', 'blank': 'True'}), + 'added_at': ('django.db.models.fields.DateTimeField', [], {'default': 'datetime.datetime.now'}), + 'author': ('django.db.models.fields.related.ForeignKey', [], {'related_name': "'answers'", 'to': "orm['auth.User']"}), + 'comment_count': ('django.db.models.fields.PositiveIntegerField', [], {'default': '0'}), + 'deleted': ('django.db.models.fields.BooleanField', [], {'default': 'False', 'blank': '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_answers'", 'null': 'True', 'to': "orm['auth.User']"}), + 'html': ('django.db.models.fields.TextField', [], {}), + 'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}), + '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_answers'", 'null': 'True', 'to': "orm['auth.User']"}), + 'locked': ('django.db.models.fields.BooleanField', [], {'default': 'False', 'blank': 'True'}), + 'locked_at': ('django.db.models.fields.DateTimeField', [], {'null': 'True', 'blank': 'True'}), + 'locked_by': ('django.db.models.fields.related.ForeignKey', [], {'blank': 'True', 'related_name': "'locked_answers'", 'null': 'True', 'to': "orm['auth.User']"}), + 'offensive_flag_count': ('django.db.models.fields.SmallIntegerField', [], {'default': '0'}), + 'question': ('django.db.models.fields.related.ForeignKey', [], {'related_name': "'answers'", 'to': "orm['forum.Question']"}), + 'score': ('django.db.models.fields.IntegerField', [], {'default': '0'}), + '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', 'blank': 'True'}), + 'wikified_at': ('django.db.models.fields.DateTimeField', [], {'null': 'True', 'blank': 'True'}) + }, + 'forum.answerrevision': { + 'Meta': {'object_name': 'AnswerRevision', 'db_table': "u'answer_revision'"}, + 'answer': ('django.db.models.fields.related.ForeignKey', [], {'related_name': "'revisions'", 'to': "orm['forum.Answer']"}), + 'author': ('django.db.models.fields.related.ForeignKey', [], {'related_name': "'answerrevisions'", 'to': "orm['auth.User']"}), + 'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}), + 'revised_at': ('django.db.models.fields.DateTimeField', [], {}), + 'revision': ('django.db.models.fields.PositiveIntegerField', [], {}), + 'summary': ('django.db.models.fields.CharField', [], {'max_length': '300', 'blank': 'True'}), + 'text': ('django.db.models.fields.TextField', [], {}) + }, + 'forum.authkeyuserassociation': { + 'Meta': {'object_name': 'AuthKeyUserAssociation'}, + 'added_at': ('django.db.models.fields.DateTimeField', [], {'default': 'datetime.datetime.now'}), + 'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}), + 'key': ('django.db.models.fields.CharField', [], {'unique': 'True', 'max_length': '255'}), + 'provider': ('django.db.models.fields.CharField', [], {'max_length': '64'}), + 'user': ('django.db.models.fields.related.ForeignKey', [], {'related_name': "'auth_keys'", 'to': "orm['auth.User']"}) + }, + 'forum.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['forum.Badge']"}), + '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', 'blank': 'True'}), + 'object_id': ('django.db.models.fields.PositiveIntegerField', [], {}), + 'user': ('django.db.models.fields.related.ForeignKey', [], {'related_name': "'award_user'", 'to': "orm['auth.User']"}) + }, + 'forum.badge': { + 'Meta': {'unique_together': "(('name', 'type'),)", 'object_name': 'Badge', 'db_table': "u'badge'"}, + 'awarded_count': ('django.db.models.fields.PositiveIntegerField', [], {'default': '0'}), + 'awarded_to': ('django.db.models.fields.related.ManyToManyField', [], {'related_name': "'badges'", 'through': "'Award'", 'to': "orm['auth.User']"}), + 'description': ('django.db.models.fields.CharField', [], {'max_length': '300'}), + 'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}), + 'multiple': ('django.db.models.fields.BooleanField', [], {'default': 'False', 'blank': 'True'}), + 'name': ('django.db.models.fields.CharField', [], {'max_length': '50'}), + 'slug': ('django.db.models.fields.SlugField', [], {'db_index': 'True', 'max_length': '50', 'blank': 'True'}), + 'type': ('django.db.models.fields.SmallIntegerField', [], {}) + }, + 'forum.book': { + 'Meta': {'object_name': 'Book', 'db_table': "u'book'"}, + 'added_at': ('django.db.models.fields.DateTimeField', [], {}), + 'author': ('django.db.models.fields.CharField', [], {'max_length': '255'}), + 'cover_img': ('django.db.models.fields.CharField', [], {'max_length': '255'}), + 'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}), + 'last_edited_at': ('django.db.models.fields.DateTimeField', [], {}), + 'pages': ('django.db.models.fields.SmallIntegerField', [], {}), + 'price': ('django.db.models.fields.DecimalField', [], {'max_digits': '6', 'decimal_places': '2'}), + 'publication': ('django.db.models.fields.CharField', [], {'max_length': '255'}), + 'published_at': ('django.db.models.fields.DateTimeField', [], {}), + 'questions': ('django.db.models.fields.related.ManyToManyField', [], {'related_name': "'book'", 'db_table': "'book_question'", 'to': "orm['forum.Question']"}), + 'short_name': ('django.db.models.fields.CharField', [], {'max_length': '255'}), + 'tagnames': ('django.db.models.fields.CharField', [], {'max_length': '125'}), + 'title': ('django.db.models.fields.CharField', [], {'max_length': '255'}), + 'user': ('django.db.models.fields.related.ForeignKey', [], {'to': "orm['auth.User']"}) + }, + 'forum.bookauthorinfo': { + 'Meta': {'object_name': 'BookAuthorInfo', 'db_table': "u'book_author_info'"}, + 'added_at': ('django.db.models.fields.DateTimeField', [], {}), + 'blog_url': ('django.db.models.fields.CharField', [], {'max_length': '255'}), + 'book': ('django.db.models.fields.related.ForeignKey', [], {'to': "orm['forum.Book']"}), + 'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}), + 'last_edited_at': ('django.db.models.fields.DateTimeField', [], {}), + 'user': ('django.db.models.fields.related.ForeignKey', [], {'to': "orm['auth.User']"}) + }, + 'forum.bookauthorrss': { + 'Meta': {'object_name': 'BookAuthorRss', 'db_table': "u'book_author_rss'"}, + 'added_at': ('django.db.models.fields.DateTimeField', [], {}), + 'book': ('django.db.models.fields.related.ForeignKey', [], {'to': "orm['forum.Book']"}), + 'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}), + 'rss_created_at': ('django.db.models.fields.DateTimeField', [], {}), + 'title': ('django.db.models.fields.CharField', [], {'max_length': '255'}), + 'url': ('django.db.models.fields.CharField', [], {'max_length': '255'}), + 'user': ('django.db.models.fields.related.ForeignKey', [], {'to': "orm['auth.User']"}) + }, + 'forum.comment': { + 'Meta': {'object_name': 'Comment', 'db_table': "u'comment'"}, + 'added_at': ('django.db.models.fields.DateTimeField', [], {'default': 'datetime.datetime.now'}), + 'comment': ('django.db.models.fields.CharField', [], {'max_length': '300'}), + 'content_type': ('django.db.models.fields.related.ForeignKey', [], {'to': "orm['contenttypes.ContentType']"}), + 'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}), + 'object_id': ('django.db.models.fields.PositiveIntegerField', [], {}), + 'user': ('django.db.models.fields.related.ForeignKey', [], {'related_name': "'comments'", 'to': "orm['auth.User']"}) + }, + 'forum.emailfeedsetting': { + 'Meta': {'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', [], {'to': "orm['auth.User']"}) + }, + 'forum.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'}), + 'question': ('django.db.models.fields.related.ForeignKey', [], {'to': "orm['forum.Question']"}), + 'user': ('django.db.models.fields.related.ForeignKey', [], {'related_name': "'user_favorite_questions'", 'to': "orm['auth.User']"}) + }, + 'forum.flaggeditem': { + 'Meta': {'unique_together': "(('content_type', 'object_id', 'user'),)", 'object_name': 'FlaggedItem', 'db_table': "u'flagged_item'"}, + 'content_type': ('django.db.models.fields.related.ForeignKey', [], {'to': "orm['contenttypes.ContentType']"}), + 'flagged_at': ('django.db.models.fields.DateTimeField', [], {'default': 'datetime.datetime.now'}), + 'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}), + 'object_id': ('django.db.models.fields.PositiveIntegerField', [], {}), + 'user': ('django.db.models.fields.related.ForeignKey', [], {'related_name': "'flaggeditems'", 'to': "orm['auth.User']"}) + }, + 'forum.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['forum.Tag']"}), + 'user': ('django.db.models.fields.related.ForeignKey', [], {'related_name': "'tag_selections'", 'to': "orm['auth.User']"}) + }, + 'forum.question': { + 'Meta': {'object_name': 'Question', 'db_table': "u'question'"}, + 'added_at': ('django.db.models.fields.DateTimeField', [], {'default': 'datetime.datetime.now'}), + 'answer_accepted': ('django.db.models.fields.BooleanField', [], {'default': 'False', 'blank': 'True'}), + 'answer_count': ('django.db.models.fields.PositiveIntegerField', [], {'default': '0'}), + 'author': ('django.db.models.fields.related.ForeignKey', [], {'related_name': "'questions'", 'to': "orm['auth.User']"}), + 'close_reason': ('django.db.models.fields.SmallIntegerField', [], {'null': 'True', 'blank': 'True'}), + 'closed': ('django.db.models.fields.BooleanField', [], {'default': 'False', 'blank': 'True'}), + 'closed_at': ('django.db.models.fields.DateTimeField', [], {'null': 'True', 'blank': 'True'}), + 'closed_by': ('django.db.models.fields.related.ForeignKey', [], {'blank': 'True', 'related_name': "'closed_questions'", 'null': 'True', 'to': "orm['auth.User']"}), + 'comment_count': ('django.db.models.fields.PositiveIntegerField', [], {'default': '0'}), + 'deleted': ('django.db.models.fields.BooleanField', [], {'default': 'False', 'blank': '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_questions'", 'null': 'True', 'to': "orm['auth.User']"}), + 'favorited_by': ('django.db.models.fields.related.ManyToManyField', [], {'related_name': "'favorite_questions'", 'through': "'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_questions'", 'to': "orm['auth.User']"}), + 'html': ('django.db.models.fields.TextField', [], {}), + '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': "'last_active_in_questions'", 'to': "orm['auth.User']"}), + '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_questions'", 'null': 'True', 'to': "orm['auth.User']"}), + 'locked': ('django.db.models.fields.BooleanField', [], {'default': 'False', 'blank': 'True'}), + 'locked_at': ('django.db.models.fields.DateTimeField', [], {'null': 'True', 'blank': 'True'}), + 'locked_by': ('django.db.models.fields.related.ForeignKey', [], {'blank': 'True', 'related_name': "'locked_questions'", 'null': 'True', 'to': "orm['auth.User']"}), + 'offensive_flag_count': ('django.db.models.fields.SmallIntegerField', [], {'default': '0'}), + 'score': ('django.db.models.fields.IntegerField', [], {'default': '0'}), + 'summary': ('django.db.models.fields.CharField', [], {'max_length': '180'}), + 'tagnames': ('django.db.models.fields.CharField', [], {'max_length': '125'}), + 'tags': ('django.db.models.fields.related.ManyToManyField', [], {'related_name': "'questions'", 'to': "orm['forum.Tag']"}), + 'title': ('django.db.models.fields.CharField', [], {'max_length': '300'}), + 'view_count': ('django.db.models.fields.PositiveIntegerField', [], {'default': '0'}), + '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', 'blank': 'True'}), + 'wikified_at': ('django.db.models.fields.DateTimeField', [], {'null': 'True', 'blank': 'True'}) + }, + 'forum.questionrevision': { + 'Meta': {'object_name': 'QuestionRevision', 'db_table': "u'question_revision'"}, + 'author': ('django.db.models.fields.related.ForeignKey', [], {'related_name': "'questionrevisions'", 'to': "orm['auth.User']"}), + 'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}), + 'question': ('django.db.models.fields.related.ForeignKey', [], {'related_name': "'revisions'", 'to': "orm['forum.Question']"}), + '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', [], {'max_length': '125'}), + 'text': ('django.db.models.fields.TextField', [], {}), + 'title': ('django.db.models.fields.CharField', [], {'max_length': '300'}) + }, + 'forum.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['forum.Question']"}), + 'when': ('django.db.models.fields.DateTimeField', [], {}), + 'who': ('django.db.models.fields.related.ForeignKey', [], {'related_name': "'question_views'", 'to': "orm['auth.User']"}) + }, + 'forum.repute': { + 'Meta': {'object_name': 'Repute', 'db_table': "u'repute'"}, + '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['forum.Question']"}), + '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']"}) + }, + 'forum.tag': { + 'Meta': {'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', 'blank': '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_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'}), + 'used_count': ('django.db.models.fields.PositiveIntegerField', [], {'default': '0'}) + }, + 'forum.validationhash': { + 'Meta': {'unique_together': "(('user', 'type'),)", 'object_name': 'ValidationHash'}, + 'expiration': ('django.db.models.fields.DateTimeField', [], {'default': 'datetime.datetime(2010, 4, 25, 13, 14, 41, 714642)'}), + 'hash_code': ('django.db.models.fields.CharField', [], {'unique': 'True', 'max_length': '255'}), + 'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}), + 'seed': ('django.db.models.fields.CharField', [], {'max_length': '12'}), + 'type': ('django.db.models.fields.CharField', [], {'max_length': '12'}), + 'user': ('django.db.models.fields.related.ForeignKey', [], {'to': "orm['auth.User']"}) + }, + 'forum.vote': { + 'Meta': {'unique_together': "(('content_type', 'object_id', 'user'),)", 'object_name': 'Vote', 'db_table': "u'vote'"}, + 'content_type': ('django.db.models.fields.related.ForeignKey', [], {'to': "orm['contenttypes.ContentType']"}), + 'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}), + 'object_id': ('django.db.models.fields.PositiveIntegerField', [], {}), + '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'}) + } + } + + complete_apps = ['forum'] diff --git a/forum/migrations/0002_auto__add_field_answer_text__chg_field_answer_html__add_field_question.py b/forum/migrations/0002_auto__add_field_answer_text__chg_field_answer_html__add_field_question.py new file mode 100644 index 00000000..d703c161 --- /dev/null +++ b/forum/migrations/0002_auto__add_field_answer_text__chg_field_answer_html__add_field_question.py @@ -0,0 +1,368 @@ +# encoding: 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 field 'Answer.text' + db.add_column(u'answer', 'text', self.gf('django.db.models.fields.TextField')(null=True), keep_default=False) + + # Changing field 'Answer.html' + db.alter_column(u'answer', 'html', self.gf('django.db.models.fields.TextField')(null=True)) + + # Adding field 'Question.text' + db.add_column(u'question', 'text', self.gf('django.db.models.fields.TextField')(null=True), keep_default=False) + + # Changing field 'Question.html' + db.alter_column(u'question', 'html', self.gf('django.db.models.fields.TextField')(null=True)) + + + def backwards(self, orm): + + # Deleting field 'Answer.text' + db.delete_column(u'answer', 'text') + + # Changing field 'Answer.html' + db.alter_column(u'answer', 'html', self.gf('django.db.models.fields.TextField')()) + + # Deleting field 'Question.text' + db.delete_column(u'question', 'text') + + # Changing field 'Question.html' + db.alter_column(u'question', 'html', self.gf('django.db.models.fields.TextField')()) + + + models = { + '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']", 'blank': 'True'}) + }, + 'auth.permission': { + 'Meta': {'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'}), + 'bronze': ('django.db.models.fields.SmallIntegerField', [], {'default': '0'}), + 'date_joined': ('django.db.models.fields.DateTimeField', [], {'default': 'datetime.datetime.now'}), + 'date_of_birth': ('django.db.models.fields.DateField', [], {'null': 'True', 'blank': 'True'}), + 'email': ('django.db.models.fields.EmailField', [], {'max_length': '75', 'blank': 'True'}), + 'email_isvalid': ('django.db.models.fields.BooleanField', [], {'default': 'False', 'blank': 'True'}), + 'email_key': ('django.db.models.fields.CharField', [], {'max_length': '32', 'null': 'True'}), + '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']", 'blank': 'True'}), + 'hide_ignored_questions': ('django.db.models.fields.BooleanField', [], {'default': 'False', 'blank': 'True'}), + 'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}), + 'is_active': ('django.db.models.fields.BooleanField', [], {'default': 'True', 'blank': 'True'}), + 'is_approved': ('django.db.models.fields.BooleanField', [], {'default': 'False', 'blank': 'True'}), + 'is_staff': ('django.db.models.fields.BooleanField', [], {'default': 'False', 'blank': 'True'}), + 'is_superuser': ('django.db.models.fields.BooleanField', [], {'default': 'False', 'blank': 'True'}), + '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'}), + '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'}), + 'silver': ('django.db.models.fields.SmallIntegerField', [], {'default': '0'}), + 'tag_filter_setting': ('django.db.models.fields.CharField', [], {'default': "'ignored'", 'max_length': '16'}), + 'user_permissions': ('django.db.models.fields.related.ManyToManyField', [], {'to': "orm['auth.Permission']", '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': {'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'}) + }, + 'forum.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', 'blank': 'True'}), + 'object_id': ('django.db.models.fields.PositiveIntegerField', [], {}), + 'user': ('django.db.models.fields.related.ForeignKey', [], {'to': "orm['auth.User']"}) + }, + 'forum.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['forum.Question']"}), + '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', 'blank': 'True'}) + }, + 'forum.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'}), + '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', 'blank': 'True'}) + }, + 'forum.answer': { + 'Meta': {'object_name': 'Answer', 'db_table': "u'answer'"}, + 'accepted': ('django.db.models.fields.BooleanField', [], {'default': 'False', 'blank': 'True'}), + 'accepted_at': ('django.db.models.fields.DateTimeField', [], {'null': 'True', 'blank': 'True'}), + 'added_at': ('django.db.models.fields.DateTimeField', [], {'default': 'datetime.datetime.now'}), + 'author': ('django.db.models.fields.related.ForeignKey', [], {'related_name': "'answers'", 'to': "orm['auth.User']"}), + 'comment_count': ('django.db.models.fields.PositiveIntegerField', [], {'default': '0'}), + 'deleted': ('django.db.models.fields.BooleanField', [], {'default': 'False', 'blank': '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_answers'", 'null': 'True', 'to': "orm['auth.User']"}), + 'html': ('django.db.models.fields.TextField', [], {'null': 'True'}), + 'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}), + '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_answers'", 'null': 'True', 'to': "orm['auth.User']"}), + 'locked': ('django.db.models.fields.BooleanField', [], {'default': 'False', 'blank': 'True'}), + 'locked_at': ('django.db.models.fields.DateTimeField', [], {'null': 'True', 'blank': 'True'}), + 'locked_by': ('django.db.models.fields.related.ForeignKey', [], {'blank': 'True', 'related_name': "'locked_answers'", 'null': 'True', 'to': "orm['auth.User']"}), + 'offensive_flag_count': ('django.db.models.fields.SmallIntegerField', [], {'default': '0'}), + 'question': ('django.db.models.fields.related.ForeignKey', [], {'related_name': "'answers'", 'to': "orm['forum.Question']"}), + 'score': ('django.db.models.fields.IntegerField', [], {'default': '0'}), + 'text': ('django.db.models.fields.TextField', [], {'null': 'True'}), + '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', 'blank': 'True'}), + 'wikified_at': ('django.db.models.fields.DateTimeField', [], {'null': 'True', 'blank': 'True'}) + }, + 'forum.answerrevision': { + 'Meta': {'object_name': 'AnswerRevision', 'db_table': "u'answer_revision'"}, + 'answer': ('django.db.models.fields.related.ForeignKey', [], {'related_name': "'revisions'", 'to': "orm['forum.Answer']"}), + 'author': ('django.db.models.fields.related.ForeignKey', [], {'related_name': "'answerrevisions'", 'to': "orm['auth.User']"}), + 'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}), + 'revised_at': ('django.db.models.fields.DateTimeField', [], {}), + 'revision': ('django.db.models.fields.PositiveIntegerField', [], {}), + 'summary': ('django.db.models.fields.CharField', [], {'max_length': '300', 'blank': 'True'}), + 'text': ('django.db.models.fields.TextField', [], {}) + }, + 'forum.authkeyuserassociation': { + 'Meta': {'object_name': 'AuthKeyUserAssociation'}, + 'added_at': ('django.db.models.fields.DateTimeField', [], {'default': 'datetime.datetime.now'}), + 'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}), + 'key': ('django.db.models.fields.CharField', [], {'unique': 'True', 'max_length': '255'}), + 'provider': ('django.db.models.fields.CharField', [], {'max_length': '64'}), + 'user': ('django.db.models.fields.related.ForeignKey', [], {'related_name': "'auth_keys'", 'to': "orm['auth.User']"}) + }, + 'forum.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['forum.Badge']"}), + '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', 'blank': 'True'}), + 'object_id': ('django.db.models.fields.PositiveIntegerField', [], {}), + 'user': ('django.db.models.fields.related.ForeignKey', [], {'related_name': "'award_user'", 'to': "orm['auth.User']"}) + }, + 'forum.badge': { + 'Meta': {'unique_together': "(('name', 'type'),)", 'object_name': 'Badge', 'db_table': "u'badge'"}, + 'awarded_count': ('django.db.models.fields.PositiveIntegerField', [], {'default': '0'}), + 'awarded_to': ('django.db.models.fields.related.ManyToManyField', [], {'related_name': "'badges'", 'through': "'Award'", 'to': "orm['auth.User']"}), + 'description': ('django.db.models.fields.CharField', [], {'max_length': '300'}), + 'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}), + 'multiple': ('django.db.models.fields.BooleanField', [], {'default': 'False', 'blank': 'True'}), + 'name': ('django.db.models.fields.CharField', [], {'max_length': '50'}), + 'slug': ('django.db.models.fields.SlugField', [], {'db_index': 'True', 'max_length': '50', 'blank': 'True'}), + 'type': ('django.db.models.fields.SmallIntegerField', [], {}) + }, + 'forum.book': { + 'Meta': {'object_name': 'Book', 'db_table': "u'book'"}, + 'added_at': ('django.db.models.fields.DateTimeField', [], {}), + 'author': ('django.db.models.fields.CharField', [], {'max_length': '255'}), + 'cover_img': ('django.db.models.fields.CharField', [], {'max_length': '255'}), + 'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}), + 'last_edited_at': ('django.db.models.fields.DateTimeField', [], {}), + 'pages': ('django.db.models.fields.SmallIntegerField', [], {}), + 'price': ('django.db.models.fields.DecimalField', [], {'max_digits': '6', 'decimal_places': '2'}), + 'publication': ('django.db.models.fields.CharField', [], {'max_length': '255'}), + 'published_at': ('django.db.models.fields.DateTimeField', [], {}), + 'questions': ('django.db.models.fields.related.ManyToManyField', [], {'related_name': "'book'", 'db_table': "'book_question'", 'to': "orm['forum.Question']"}), + 'short_name': ('django.db.models.fields.CharField', [], {'max_length': '255'}), + 'tagnames': ('django.db.models.fields.CharField', [], {'max_length': '125'}), + 'title': ('django.db.models.fields.CharField', [], {'max_length': '255'}), + 'user': ('django.db.models.fields.related.ForeignKey', [], {'to': "orm['auth.User']"}) + }, + 'forum.bookauthorinfo': { + 'Meta': {'object_name': 'BookAuthorInfo', 'db_table': "u'book_author_info'"}, + 'added_at': ('django.db.models.fields.DateTimeField', [], {}), + 'blog_url': ('django.db.models.fields.CharField', [], {'max_length': '255'}), + 'book': ('django.db.models.fields.related.ForeignKey', [], {'to': "orm['forum.Book']"}), + 'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}), + 'last_edited_at': ('django.db.models.fields.DateTimeField', [], {}), + 'user': ('django.db.models.fields.related.ForeignKey', [], {'to': "orm['auth.User']"}) + }, + 'forum.bookauthorrss': { + 'Meta': {'object_name': 'BookAuthorRss', 'db_table': "u'book_author_rss'"}, + 'added_at': ('django.db.models.fields.DateTimeField', [], {}), + 'book': ('django.db.models.fields.related.ForeignKey', [], {'to': "orm['forum.Book']"}), + 'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}), + 'rss_created_at': ('django.db.models.fields.DateTimeField', [], {}), + 'title': ('django.db.models.fields.CharField', [], {'max_length': '255'}), + 'url': ('django.db.models.fields.CharField', [], {'max_length': '255'}), + 'user': ('django.db.models.fields.related.ForeignKey', [], {'to': "orm['auth.User']"}) + }, + 'forum.comment': { + 'Meta': {'object_name': 'Comment', 'db_table': "u'comment'"}, + 'added_at': ('django.db.models.fields.DateTimeField', [], {'default': 'datetime.datetime.now'}), + 'comment': ('django.db.models.fields.CharField', [], {'max_length': '300'}), + 'content_type': ('django.db.models.fields.related.ForeignKey', [], {'to': "orm['contenttypes.ContentType']"}), + 'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}), + 'object_id': ('django.db.models.fields.PositiveIntegerField', [], {}), + 'user': ('django.db.models.fields.related.ForeignKey', [], {'related_name': "'comments'", 'to': "orm['auth.User']"}) + }, + 'forum.emailfeedsetting': { + 'Meta': {'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', [], {'to': "orm['auth.User']"}) + }, + 'forum.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'}), + 'question': ('django.db.models.fields.related.ForeignKey', [], {'to': "orm['forum.Question']"}), + 'user': ('django.db.models.fields.related.ForeignKey', [], {'related_name': "'user_favorite_questions'", 'to': "orm['auth.User']"}) + }, + 'forum.flaggeditem': { + 'Meta': {'unique_together': "(('content_type', 'object_id', 'user'),)", 'object_name': 'FlaggedItem', 'db_table': "u'flagged_item'"}, + 'content_type': ('django.db.models.fields.related.ForeignKey', [], {'to': "orm['contenttypes.ContentType']"}), + 'flagged_at': ('django.db.models.fields.DateTimeField', [], {'default': 'datetime.datetime.now'}), + 'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}), + 'object_id': ('django.db.models.fields.PositiveIntegerField', [], {}), + 'user': ('django.db.models.fields.related.ForeignKey', [], {'related_name': "'flaggeditems'", 'to': "orm['auth.User']"}) + }, + 'forum.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['forum.Tag']"}), + 'user': ('django.db.models.fields.related.ForeignKey', [], {'related_name': "'tag_selections'", 'to': "orm['auth.User']"}) + }, + 'forum.question': { + 'Meta': {'object_name': 'Question', 'db_table': "u'question'"}, + 'added_at': ('django.db.models.fields.DateTimeField', [], {'default': 'datetime.datetime.now'}), + 'answer_accepted': ('django.db.models.fields.BooleanField', [], {'default': 'False', 'blank': 'True'}), + 'answer_count': ('django.db.models.fields.PositiveIntegerField', [], {'default': '0'}), + 'author': ('django.db.models.fields.related.ForeignKey', [], {'related_name': "'questions'", 'to': "orm['auth.User']"}), + 'close_reason': ('django.db.models.fields.SmallIntegerField', [], {'null': 'True', 'blank': 'True'}), + 'closed': ('django.db.models.fields.BooleanField', [], {'default': 'False', 'blank': 'True'}), + 'closed_at': ('django.db.models.fields.DateTimeField', [], {'null': 'True', 'blank': 'True'}), + 'closed_by': ('django.db.models.fields.related.ForeignKey', [], {'blank': 'True', 'related_name': "'closed_questions'", 'null': 'True', 'to': "orm['auth.User']"}), + 'comment_count': ('django.db.models.fields.PositiveIntegerField', [], {'default': '0'}), + 'deleted': ('django.db.models.fields.BooleanField', [], {'default': 'False', 'blank': '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_questions'", 'null': 'True', 'to': "orm['auth.User']"}), + 'favorited_by': ('django.db.models.fields.related.ManyToManyField', [], {'related_name': "'favorite_questions'", 'through': "'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_questions'", 'to': "orm['auth.User']"}), + 'html': ('django.db.models.fields.TextField', [], {'null': 'True'}), + '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': "'last_active_in_questions'", 'to': "orm['auth.User']"}), + '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_questions'", 'null': 'True', 'to': "orm['auth.User']"}), + 'locked': ('django.db.models.fields.BooleanField', [], {'default': 'False', 'blank': 'True'}), + 'locked_at': ('django.db.models.fields.DateTimeField', [], {'null': 'True', 'blank': 'True'}), + 'locked_by': ('django.db.models.fields.related.ForeignKey', [], {'blank': 'True', 'related_name': "'locked_questions'", 'null': 'True', 'to': "orm['auth.User']"}), + 'offensive_flag_count': ('django.db.models.fields.SmallIntegerField', [], {'default': '0'}), + 'score': ('django.db.models.fields.IntegerField', [], {'default': '0'}), + 'summary': ('django.db.models.fields.CharField', [], {'max_length': '180'}), + 'tagnames': ('django.db.models.fields.CharField', [], {'max_length': '125'}), + 'tags': ('django.db.models.fields.related.ManyToManyField', [], {'related_name': "'questions'", 'to': "orm['forum.Tag']"}), + 'text': ('django.db.models.fields.TextField', [], {'null': 'True'}), + 'title': ('django.db.models.fields.CharField', [], {'max_length': '300'}), + 'view_count': ('django.db.models.fields.PositiveIntegerField', [], {'default': '0'}), + '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', 'blank': 'True'}), + 'wikified_at': ('django.db.models.fields.DateTimeField', [], {'null': 'True', 'blank': 'True'}) + }, + 'forum.questionrevision': { + 'Meta': {'object_name': 'QuestionRevision', 'db_table': "u'question_revision'"}, + 'author': ('django.db.models.fields.related.ForeignKey', [], {'related_name': "'questionrevisions'", 'to': "orm['auth.User']"}), + 'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}), + 'question': ('django.db.models.fields.related.ForeignKey', [], {'related_name': "'revisions'", 'to': "orm['forum.Question']"}), + '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', [], {'max_length': '125'}), + 'text': ('django.db.models.fields.TextField', [], {}), + 'title': ('django.db.models.fields.CharField', [], {'max_length': '300'}) + }, + 'forum.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['forum.Question']"}), + 'when': ('django.db.models.fields.DateTimeField', [], {}), + 'who': ('django.db.models.fields.related.ForeignKey', [], {'related_name': "'question_views'", 'to': "orm['auth.User']"}) + }, + 'forum.repute': { + 'Meta': {'object_name': 'Repute', 'db_table': "u'repute'"}, + '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['forum.Question']"}), + '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']"}) + }, + 'forum.tag': { + 'Meta': {'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', 'blank': '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_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'}), + 'used_count': ('django.db.models.fields.PositiveIntegerField', [], {'default': '0'}) + }, + 'forum.validationhash': { + 'Meta': {'unique_together': "(('user', 'type'),)", 'object_name': 'ValidationHash'}, + 'expiration': ('django.db.models.fields.DateTimeField', [], {'default': 'datetime.datetime(2010, 4, 25, 16, 21, 32, 856067)'}), + 'hash_code': ('django.db.models.fields.CharField', [], {'unique': 'True', 'max_length': '255'}), + 'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}), + 'seed': ('django.db.models.fields.CharField', [], {'max_length': '12'}), + 'type': ('django.db.models.fields.CharField', [], {'max_length': '12'}), + 'user': ('django.db.models.fields.related.ForeignKey', [], {'to': "orm['auth.User']"}) + }, + 'forum.vote': { + 'Meta': {'unique_together': "(('content_type', 'object_id', 'user'),)", 'object_name': 'Vote', 'db_table': "u'vote'"}, + 'content_type': ('django.db.models.fields.related.ForeignKey', [], {'to': "orm['contenttypes.ContentType']"}), + 'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}), + 'object_id': ('django.db.models.fields.PositiveIntegerField', [], {}), + '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'}) + } + } + + complete_apps = ['forum'] diff --git a/forum/migrations/0003_copy_denorm_text_record_to_posts_for_fulltext_search.py b/forum/migrations/0003_copy_denorm_text_record_to_posts_for_fulltext_search.py new file mode 100644 index 00000000..3e79b9d2 --- /dev/null +++ b/forum/migrations/0003_copy_denorm_text_record_to_posts_for_fulltext_search.py @@ -0,0 +1,354 @@ +# encoding: utf-8 +import datetime +from south.db import db +from south.v2 import DataMigration +from django.db import models +from forum.models import Question, Answer + +class Migration(DataMigration): + + def forwards(self, orm): + "Write your forwards methods here." + for q in orm.Question.objects.all(): + r = q.revisions.all()[0] #cannot use get_latest_revision() + q.text = r.text + q.save() + for a in orm.Answer.objects.all(): + r = a.revisions.all()[0] + a.text = r.text + a.save() + + def backwards(self, orm): + "Write your backwards methods here." + pass#there's no need to clean data here, just delete columns + + models = { + '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']", 'blank': 'True'}) + }, + 'auth.permission': { + 'Meta': {'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'}), + 'bronze': ('django.db.models.fields.SmallIntegerField', [], {'default': '0'}), + 'date_joined': ('django.db.models.fields.DateTimeField', [], {'default': 'datetime.datetime.now'}), + 'date_of_birth': ('django.db.models.fields.DateField', [], {'null': 'True', 'blank': 'True'}), + 'email': ('django.db.models.fields.EmailField', [], {'max_length': '75', 'blank': 'True'}), + 'email_isvalid': ('django.db.models.fields.BooleanField', [], {'default': 'False', 'blank': 'True'}), + 'email_key': ('django.db.models.fields.CharField', [], {'max_length': '32', 'null': 'True'}), + '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']", 'blank': 'True'}), + 'hide_ignored_questions': ('django.db.models.fields.BooleanField', [], {'default': 'False', 'blank': 'True'}), + 'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}), + 'is_active': ('django.db.models.fields.BooleanField', [], {'default': 'True', 'blank': 'True'}), + 'is_approved': ('django.db.models.fields.BooleanField', [], {'default': 'False', 'blank': 'True'}), + 'is_staff': ('django.db.models.fields.BooleanField', [], {'default': 'False', 'blank': 'True'}), + 'is_superuser': ('django.db.models.fields.BooleanField', [], {'default': 'False', 'blank': 'True'}), + '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'}), + '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'}), + 'silver': ('django.db.models.fields.SmallIntegerField', [], {'default': '0'}), + 'tag_filter_setting': ('django.db.models.fields.CharField', [], {'default': "'ignored'", 'max_length': '16'}), + 'user_permissions': ('django.db.models.fields.related.ManyToManyField', [], {'to': "orm['auth.Permission']", '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': {'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'}) + }, + 'forum.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', 'blank': 'True'}), + 'object_id': ('django.db.models.fields.PositiveIntegerField', [], {}), + 'user': ('django.db.models.fields.related.ForeignKey', [], {'to': "orm['auth.User']"}) + }, + 'forum.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['forum.Question']"}), + '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', 'blank': 'True'}) + }, + 'forum.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'}), + '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', 'blank': 'True'}) + }, + 'forum.answer': { + 'Meta': {'object_name': 'Answer', 'db_table': "u'answer'"}, + 'accepted': ('django.db.models.fields.BooleanField', [], {'default': 'False', 'blank': 'True'}), + 'accepted_at': ('django.db.models.fields.DateTimeField', [], {'null': 'True', 'blank': 'True'}), + 'added_at': ('django.db.models.fields.DateTimeField', [], {'default': 'datetime.datetime.now'}), + 'author': ('django.db.models.fields.related.ForeignKey', [], {'related_name': "'answers'", 'to': "orm['auth.User']"}), + 'comment_count': ('django.db.models.fields.PositiveIntegerField', [], {'default': '0'}), + 'deleted': ('django.db.models.fields.BooleanField', [], {'default': 'False', 'blank': '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_answers'", 'null': 'True', 'to': "orm['auth.User']"}), + 'html': ('django.db.models.fields.TextField', [], {'null': 'True'}), + 'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}), + '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_answers'", 'null': 'True', 'to': "orm['auth.User']"}), + 'locked': ('django.db.models.fields.BooleanField', [], {'default': 'False', 'blank': 'True'}), + 'locked_at': ('django.db.models.fields.DateTimeField', [], {'null': 'True', 'blank': 'True'}), + 'locked_by': ('django.db.models.fields.related.ForeignKey', [], {'blank': 'True', 'related_name': "'locked_answers'", 'null': 'True', 'to': "orm['auth.User']"}), + 'offensive_flag_count': ('django.db.models.fields.SmallIntegerField', [], {'default': '0'}), + 'question': ('django.db.models.fields.related.ForeignKey', [], {'related_name': "'answers'", 'to': "orm['forum.Question']"}), + 'score': ('django.db.models.fields.IntegerField', [], {'default': '0'}), + 'text': ('django.db.models.fields.TextField', [], {'null': 'True'}), + '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', 'blank': 'True'}), + 'wikified_at': ('django.db.models.fields.DateTimeField', [], {'null': 'True', 'blank': 'True'}) + }, + 'forum.answerrevision': { + 'Meta': {'object_name': 'AnswerRevision', 'db_table': "u'answer_revision'"}, + 'answer': ('django.db.models.fields.related.ForeignKey', [], {'related_name': "'revisions'", 'to': "orm['forum.Answer']"}), + 'author': ('django.db.models.fields.related.ForeignKey', [], {'related_name': "'answerrevisions'", 'to': "orm['auth.User']"}), + 'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}), + 'revised_at': ('django.db.models.fields.DateTimeField', [], {}), + 'revision': ('django.db.models.fields.PositiveIntegerField', [], {}), + 'summary': ('django.db.models.fields.CharField', [], {'max_length': '300', 'blank': 'True'}), + 'text': ('django.db.models.fields.TextField', [], {}) + }, + 'forum.authkeyuserassociation': { + 'Meta': {'object_name': 'AuthKeyUserAssociation'}, + 'added_at': ('django.db.models.fields.DateTimeField', [], {'default': 'datetime.datetime.now'}), + 'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}), + 'key': ('django.db.models.fields.CharField', [], {'unique': 'True', 'max_length': '255'}), + 'provider': ('django.db.models.fields.CharField', [], {'max_length': '64'}), + 'user': ('django.db.models.fields.related.ForeignKey', [], {'related_name': "'auth_keys'", 'to': "orm['auth.User']"}) + }, + 'forum.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['forum.Badge']"}), + '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', 'blank': 'True'}), + 'object_id': ('django.db.models.fields.PositiveIntegerField', [], {}), + 'user': ('django.db.models.fields.related.ForeignKey', [], {'related_name': "'award_user'", 'to': "orm['auth.User']"}) + }, + 'forum.badge': { + 'Meta': {'unique_together': "(('name', 'type'),)", 'object_name': 'Badge', 'db_table': "u'badge'"}, + 'awarded_count': ('django.db.models.fields.PositiveIntegerField', [], {'default': '0'}), + 'awarded_to': ('django.db.models.fields.related.ManyToManyField', [], {'related_name': "'badges'", 'through': "'Award'", 'to': "orm['auth.User']"}), + 'description': ('django.db.models.fields.CharField', [], {'max_length': '300'}), + 'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}), + 'multiple': ('django.db.models.fields.BooleanField', [], {'default': 'False', 'blank': 'True'}), + 'name': ('django.db.models.fields.CharField', [], {'max_length': '50'}), + 'slug': ('django.db.models.fields.SlugField', [], {'db_index': 'True', 'max_length': '50', 'blank': 'True'}), + 'type': ('django.db.models.fields.SmallIntegerField', [], {}) + }, + 'forum.book': { + 'Meta': {'object_name': 'Book', 'db_table': "u'book'"}, + 'added_at': ('django.db.models.fields.DateTimeField', [], {}), + 'author': ('django.db.models.fields.CharField', [], {'max_length': '255'}), + 'cover_img': ('django.db.models.fields.CharField', [], {'max_length': '255'}), + 'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}), + 'last_edited_at': ('django.db.models.fields.DateTimeField', [], {}), + 'pages': ('django.db.models.fields.SmallIntegerField', [], {}), + 'price': ('django.db.models.fields.DecimalField', [], {'max_digits': '6', 'decimal_places': '2'}), + 'publication': ('django.db.models.fields.CharField', [], {'max_length': '255'}), + 'published_at': ('django.db.models.fields.DateTimeField', [], {}), + 'questions': ('django.db.models.fields.related.ManyToManyField', [], {'related_name': "'book'", 'db_table': "'book_question'", 'to': "orm['forum.Question']"}), + 'short_name': ('django.db.models.fields.CharField', [], {'max_length': '255'}), + 'tagnames': ('django.db.models.fields.CharField', [], {'max_length': '125'}), + 'title': ('django.db.models.fields.CharField', [], {'max_length': '255'}), + 'user': ('django.db.models.fields.related.ForeignKey', [], {'to': "orm['auth.User']"}) + }, + 'forum.bookauthorinfo': { + 'Meta': {'object_name': 'BookAuthorInfo', 'db_table': "u'book_author_info'"}, + 'added_at': ('django.db.models.fields.DateTimeField', [], {}), + 'blog_url': ('django.db.models.fields.CharField', [], {'max_length': '255'}), + 'book': ('django.db.models.fields.related.ForeignKey', [], {'to': "orm['forum.Book']"}), + 'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}), + 'last_edited_at': ('django.db.models.fields.DateTimeField', [], {}), + 'user': ('django.db.models.fields.related.ForeignKey', [], {'to': "orm['auth.User']"}) + }, + 'forum.bookauthorrss': { + 'Meta': {'object_name': 'BookAuthorRss', 'db_table': "u'book_author_rss'"}, + 'added_at': ('django.db.models.fields.DateTimeField', [], {}), + 'book': ('django.db.models.fields.related.ForeignKey', [], {'to': "orm['forum.Book']"}), + 'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}), + 'rss_created_at': ('django.db.models.fields.DateTimeField', [], {}), + 'title': ('django.db.models.fields.CharField', [], {'max_length': '255'}), + 'url': ('django.db.models.fields.CharField', [], {'max_length': '255'}), + 'user': ('django.db.models.fields.related.ForeignKey', [], {'to': "orm['auth.User']"}) + }, + 'forum.comment': { + 'Meta': {'object_name': 'Comment', 'db_table': "u'comment'"}, + 'added_at': ('django.db.models.fields.DateTimeField', [], {'default': 'datetime.datetime.now'}), + 'comment': ('django.db.models.fields.CharField', [], {'max_length': '300'}), + 'content_type': ('django.db.models.fields.related.ForeignKey', [], {'to': "orm['contenttypes.ContentType']"}), + 'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}), + 'object_id': ('django.db.models.fields.PositiveIntegerField', [], {}), + 'user': ('django.db.models.fields.related.ForeignKey', [], {'related_name': "'comments'", 'to': "orm['auth.User']"}) + }, + 'forum.emailfeedsetting': { + 'Meta': {'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', [], {'to': "orm['auth.User']"}) + }, + 'forum.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'}), + 'question': ('django.db.models.fields.related.ForeignKey', [], {'to': "orm['forum.Question']"}), + 'user': ('django.db.models.fields.related.ForeignKey', [], {'related_name': "'user_favorite_questions'", 'to': "orm['auth.User']"}) + }, + 'forum.flaggeditem': { + 'Meta': {'unique_together': "(('content_type', 'object_id', 'user'),)", 'object_name': 'FlaggedItem', 'db_table': "u'flagged_item'"}, + 'content_type': ('django.db.models.fields.related.ForeignKey', [], {'to': "orm['contenttypes.ContentType']"}), + 'flagged_at': ('django.db.models.fields.DateTimeField', [], {'default': 'datetime.datetime.now'}), + 'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}), + 'object_id': ('django.db.models.fields.PositiveIntegerField', [], {}), + 'user': ('django.db.models.fields.related.ForeignKey', [], {'related_name': "'flaggeditems'", 'to': "orm['auth.User']"}) + }, + 'forum.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['forum.Tag']"}), + 'user': ('django.db.models.fields.related.ForeignKey', [], {'related_name': "'tag_selections'", 'to': "orm['auth.User']"}) + }, + 'forum.question': { + 'Meta': {'object_name': 'Question', 'db_table': "u'question'"}, + 'added_at': ('django.db.models.fields.DateTimeField', [], {'default': 'datetime.datetime.now'}), + 'answer_accepted': ('django.db.models.fields.BooleanField', [], {'default': 'False', 'blank': 'True'}), + 'answer_count': ('django.db.models.fields.PositiveIntegerField', [], {'default': '0'}), + 'author': ('django.db.models.fields.related.ForeignKey', [], {'related_name': "'questions'", 'to': "orm['auth.User']"}), + 'close_reason': ('django.db.models.fields.SmallIntegerField', [], {'null': 'True', 'blank': 'True'}), + 'closed': ('django.db.models.fields.BooleanField', [], {'default': 'False', 'blank': 'True'}), + 'closed_at': ('django.db.models.fields.DateTimeField', [], {'null': 'True', 'blank': 'True'}), + 'closed_by': ('django.db.models.fields.related.ForeignKey', [], {'blank': 'True', 'related_name': "'closed_questions'", 'null': 'True', 'to': "orm['auth.User']"}), + 'comment_count': ('django.db.models.fields.PositiveIntegerField', [], {'default': '0'}), + 'deleted': ('django.db.models.fields.BooleanField', [], {'default': 'False', 'blank': '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_questions'", 'null': 'True', 'to': "orm['auth.User']"}), + 'favorited_by': ('django.db.models.fields.related.ManyToManyField', [], {'related_name': "'favorite_questions'", 'through': "'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_questions'", 'to': "orm['auth.User']"}), + 'html': ('django.db.models.fields.TextField', [], {'null': 'True'}), + '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': "'last_active_in_questions'", 'to': "orm['auth.User']"}), + '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_questions'", 'null': 'True', 'to': "orm['auth.User']"}), + 'locked': ('django.db.models.fields.BooleanField', [], {'default': 'False', 'blank': 'True'}), + 'locked_at': ('django.db.models.fields.DateTimeField', [], {'null': 'True', 'blank': 'True'}), + 'locked_by': ('django.db.models.fields.related.ForeignKey', [], {'blank': 'True', 'related_name': "'locked_questions'", 'null': 'True', 'to': "orm['auth.User']"}), + 'offensive_flag_count': ('django.db.models.fields.SmallIntegerField', [], {'default': '0'}), + 'score': ('django.db.models.fields.IntegerField', [], {'default': '0'}), + 'summary': ('django.db.models.fields.CharField', [], {'max_length': '180'}), + 'tagnames': ('django.db.models.fields.CharField', [], {'max_length': '125'}), + 'tags': ('django.db.models.fields.related.ManyToManyField', [], {'related_name': "'questions'", 'to': "orm['forum.Tag']"}), + 'text': ('django.db.models.fields.TextField', [], {'null': 'True'}), + 'title': ('django.db.models.fields.CharField', [], {'max_length': '300'}), + 'view_count': ('django.db.models.fields.PositiveIntegerField', [], {'default': '0'}), + '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', 'blank': 'True'}), + 'wikified_at': ('django.db.models.fields.DateTimeField', [], {'null': 'True', 'blank': 'True'}) + }, + 'forum.questionrevision': { + 'Meta': {'object_name': 'QuestionRevision', 'db_table': "u'question_revision'"}, + 'author': ('django.db.models.fields.related.ForeignKey', [], {'related_name': "'questionrevisions'", 'to': "orm['auth.User']"}), + 'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}), + 'question': ('django.db.models.fields.related.ForeignKey', [], {'related_name': "'revisions'", 'to': "orm['forum.Question']"}), + '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', [], {'max_length': '125'}), + 'text': ('django.db.models.fields.TextField', [], {}), + 'title': ('django.db.models.fields.CharField', [], {'max_length': '300'}) + }, + 'forum.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['forum.Question']"}), + 'when': ('django.db.models.fields.DateTimeField', [], {}), + 'who': ('django.db.models.fields.related.ForeignKey', [], {'related_name': "'question_views'", 'to': "orm['auth.User']"}) + }, + 'forum.repute': { + 'Meta': {'object_name': 'Repute', 'db_table': "u'repute'"}, + '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['forum.Question']"}), + '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']"}) + }, + 'forum.tag': { + 'Meta': {'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', 'blank': '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_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'}), + 'used_count': ('django.db.models.fields.PositiveIntegerField', [], {'default': '0'}) + }, + 'forum.validationhash': { + 'Meta': {'unique_together': "(('user', 'type'),)", 'object_name': 'ValidationHash'}, + 'expiration': ('django.db.models.fields.DateTimeField', [], {'default': 'datetime.datetime(2010, 4, 25, 16, 24, 24, 604164)'}), + 'hash_code': ('django.db.models.fields.CharField', [], {'unique': 'True', 'max_length': '255'}), + 'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}), + 'seed': ('django.db.models.fields.CharField', [], {'max_length': '12'}), + 'type': ('django.db.models.fields.CharField', [], {'max_length': '12'}), + 'user': ('django.db.models.fields.related.ForeignKey', [], {'to': "orm['auth.User']"}) + }, + 'forum.vote': { + 'Meta': {'unique_together': "(('content_type', 'object_id', 'user'),)", 'object_name': 'Vote', 'db_table': "u'vote'"}, + 'content_type': ('django.db.models.fields.related.ForeignKey', [], {'to': "orm['contenttypes.ContentType']"}), + 'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}), + 'object_id': ('django.db.models.fields.PositiveIntegerField', [], {}), + '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'}) + } + } + + complete_apps = ['forum'] diff --git a/forum/migrations/0004_install_full_text_indexes_for_mysql.py b/forum/migrations/0004_install_full_text_indexes_for_mysql.py new file mode 100644 index 00000000..0c52c442 --- /dev/null +++ b/forum/migrations/0004_install_full_text_indexes_for_mysql.py @@ -0,0 +1,389 @@ +# encoding: utf-8 +import datetime +from south.db import db +from south.v2 import DataMigration +from django.db import models +from forum.models import Question, Answer + +Q_INDEX_NAME = 'askbot_question_full_text_index' +A_INDEX_NAME = 'askbot_answer_full_text_index' +Q_TABLE_NAME = Question._meta.db_table +A_TABLE_NAME = Answer._meta.db_table + +def get_create_full_text_index_sql(index_name, table_name, column_list): + column_sql = '(%s)' % ','.join(column_list) + sql = 'CREATE FULLTEXT INDEX %s on %s %s' % (index_name, table_name, column_sql) + return sql + +def get_drop_index_sql(index_name, table_name): + return 'ALTER TABLE %s DROP INDEX %s' % (table_name, index_name) + +class Migration(DataMigration): + + def forwards(self, orm): + """install fulltext indices for mysql + will work only for MyISAM engine + and will probably fail otherwise + """ + if db.backend_name == 'mysql': + #todo: extract column names by introspection + question_index_sql = get_create_full_text_index_sql( + Q_INDEX_NAME, + Q_TABLE_NAME, + ('title','text','tagnames',) + ) + db.execute(question_index_sql) + + answer_index_sql = get_create_full_text_index_sql( + A_INDEX_NAME, + A_TABLE_NAME, + ('text',) + ) + db.execute(answer_index_sql) + + def backwards(self, orm): + "code for removal of full text indices in mysql" + if db.backend_name == 'mysql': + db.execute( + get_drop_index_sql( + Q_INDEX_NAME, + Q_TABLE_NAME, + ) + ) + db.execute( + get_drop_index_sql( + A_INDEX_NAME, + A_TABLE_NAME, + ) + ) + + models = { + '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']", 'blank': 'True'}) + }, + 'auth.permission': { + 'Meta': {'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'}), + 'bronze': ('django.db.models.fields.SmallIntegerField', [], {'default': '0'}), + 'date_joined': ('django.db.models.fields.DateTimeField', [], {'default': 'datetime.datetime.now'}), + 'date_of_birth': ('django.db.models.fields.DateField', [], {'null': 'True', 'blank': 'True'}), + 'email': ('django.db.models.fields.EmailField', [], {'max_length': '75', 'blank': 'True'}), + 'email_isvalid': ('django.db.models.fields.BooleanField', [], {'default': 'False', 'blank': 'True'}), + 'email_key': ('django.db.models.fields.CharField', [], {'max_length': '32', 'null': 'True'}), + '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']", 'blank': 'True'}), + 'hide_ignored_questions': ('django.db.models.fields.BooleanField', [], {'default': 'False', 'blank': 'True'}), + 'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}), + 'is_active': ('django.db.models.fields.BooleanField', [], {'default': 'True', 'blank': 'True'}), + 'is_approved': ('django.db.models.fields.BooleanField', [], {'default': 'False', 'blank': 'True'}), + 'is_staff': ('django.db.models.fields.BooleanField', [], {'default': 'False', 'blank': 'True'}), + 'is_superuser': ('django.db.models.fields.BooleanField', [], {'default': 'False', 'blank': 'True'}), + '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'}), + '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'}), + 'silver': ('django.db.models.fields.SmallIntegerField', [], {'default': '0'}), + 'tag_filter_setting': ('django.db.models.fields.CharField', [], {'default': "'ignored'", 'max_length': '16'}), + 'user_permissions': ('django.db.models.fields.related.ManyToManyField', [], {'to': "orm['auth.Permission']", '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': {'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'}) + }, + 'forum.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', 'blank': 'True'}), + 'object_id': ('django.db.models.fields.PositiveIntegerField', [], {}), + 'user': ('django.db.models.fields.related.ForeignKey', [], {'to': "orm['auth.User']"}) + }, + 'forum.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['forum.Question']"}), + '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', 'blank': 'True'}) + }, + 'forum.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'}), + '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', 'blank': 'True'}) + }, + 'forum.answer': { + 'Meta': {'object_name': 'Answer', 'db_table': "u'answer'"}, + 'accepted': ('django.db.models.fields.BooleanField', [], {'default': 'False', 'blank': 'True'}), + 'accepted_at': ('django.db.models.fields.DateTimeField', [], {'null': 'True', 'blank': 'True'}), + 'added_at': ('django.db.models.fields.DateTimeField', [], {'default': 'datetime.datetime.now'}), + 'author': ('django.db.models.fields.related.ForeignKey', [], {'related_name': "'answers'", 'to': "orm['auth.User']"}), + 'comment_count': ('django.db.models.fields.PositiveIntegerField', [], {'default': '0'}), + 'deleted': ('django.db.models.fields.BooleanField', [], {'default': 'False', 'blank': '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_answers'", 'null': 'True', 'to': "orm['auth.User']"}), + 'html': ('django.db.models.fields.TextField', [], {'null': 'True'}), + 'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}), + '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_answers'", 'null': 'True', 'to': "orm['auth.User']"}), + 'locked': ('django.db.models.fields.BooleanField', [], {'default': 'False', 'blank': 'True'}), + 'locked_at': ('django.db.models.fields.DateTimeField', [], {'null': 'True', 'blank': 'True'}), + 'locked_by': ('django.db.models.fields.related.ForeignKey', [], {'blank': 'True', 'related_name': "'locked_answers'", 'null': 'True', 'to': "orm['auth.User']"}), + 'offensive_flag_count': ('django.db.models.fields.SmallIntegerField', [], {'default': '0'}), + 'question': ('django.db.models.fields.related.ForeignKey', [], {'related_name': "'answers'", 'to': "orm['forum.Question']"}), + 'score': ('django.db.models.fields.IntegerField', [], {'default': '0'}), + 'text': ('django.db.models.fields.TextField', [], {'null': 'True'}), + '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', 'blank': 'True'}), + 'wikified_at': ('django.db.models.fields.DateTimeField', [], {'null': 'True', 'blank': 'True'}) + }, + 'forum.answerrevision': { + 'Meta': {'object_name': 'AnswerRevision', 'db_table': "u'answer_revision'"}, + 'answer': ('django.db.models.fields.related.ForeignKey', [], {'related_name': "'revisions'", 'to': "orm['forum.Answer']"}), + 'author': ('django.db.models.fields.related.ForeignKey', [], {'related_name': "'answerrevisions'", 'to': "orm['auth.User']"}), + 'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}), + 'revised_at': ('django.db.models.fields.DateTimeField', [], {}), + 'revision': ('django.db.models.fields.PositiveIntegerField', [], {}), + 'summary': ('django.db.models.fields.CharField', [], {'max_length': '300', 'blank': 'True'}), + 'text': ('django.db.models.fields.TextField', [], {}) + }, + 'forum.authkeyuserassociation': { + 'Meta': {'object_name': 'AuthKeyUserAssociation'}, + 'added_at': ('django.db.models.fields.DateTimeField', [], {'default': 'datetime.datetime.now'}), + 'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}), + 'key': ('django.db.models.fields.CharField', [], {'unique': 'True', 'max_length': '255'}), + 'provider': ('django.db.models.fields.CharField', [], {'max_length': '64'}), + 'user': ('django.db.models.fields.related.ForeignKey', [], {'related_name': "'auth_keys'", 'to': "orm['auth.User']"}) + }, + 'forum.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['forum.Badge']"}), + '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', 'blank': 'True'}), + 'object_id': ('django.db.models.fields.PositiveIntegerField', [], {}), + 'user': ('django.db.models.fields.related.ForeignKey', [], {'related_name': "'award_user'", 'to': "orm['auth.User']"}) + }, + 'forum.badge': { + 'Meta': {'unique_together': "(('name', 'type'),)", 'object_name': 'Badge', 'db_table': "u'badge'"}, + 'awarded_count': ('django.db.models.fields.PositiveIntegerField', [], {'default': '0'}), + 'awarded_to': ('django.db.models.fields.related.ManyToManyField', [], {'related_name': "'badges'", 'through': "'Award'", 'to': "orm['auth.User']"}), + 'description': ('django.db.models.fields.CharField', [], {'max_length': '300'}), + 'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}), + 'multiple': ('django.db.models.fields.BooleanField', [], {'default': 'False', 'blank': 'True'}), + 'name': ('django.db.models.fields.CharField', [], {'max_length': '50'}), + 'slug': ('django.db.models.fields.SlugField', [], {'db_index': 'True', 'max_length': '50', 'blank': 'True'}), + 'type': ('django.db.models.fields.SmallIntegerField', [], {}) + }, + 'forum.book': { + 'Meta': {'object_name': 'Book', 'db_table': "u'book'"}, + 'added_at': ('django.db.models.fields.DateTimeField', [], {}), + 'author': ('django.db.models.fields.CharField', [], {'max_length': '255'}), + 'cover_img': ('django.db.models.fields.CharField', [], {'max_length': '255'}), + 'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}), + 'last_edited_at': ('django.db.models.fields.DateTimeField', [], {}), + 'pages': ('django.db.models.fields.SmallIntegerField', [], {}), + 'price': ('django.db.models.fields.DecimalField', [], {'max_digits': '6', 'decimal_places': '2'}), + 'publication': ('django.db.models.fields.CharField', [], {'max_length': '255'}), + 'published_at': ('django.db.models.fields.DateTimeField', [], {}), + 'questions': ('django.db.models.fields.related.ManyToManyField', [], {'related_name': "'book'", 'db_table': "'book_question'", 'to': "orm['forum.Question']"}), + 'short_name': ('django.db.models.fields.CharField', [], {'max_length': '255'}), + 'tagnames': ('django.db.models.fields.CharField', [], {'max_length': '125'}), + 'title': ('django.db.models.fields.CharField', [], {'max_length': '255'}), + 'user': ('django.db.models.fields.related.ForeignKey', [], {'to': "orm['auth.User']"}) + }, + 'forum.bookauthorinfo': { + 'Meta': {'object_name': 'BookAuthorInfo', 'db_table': "u'book_author_info'"}, + 'added_at': ('django.db.models.fields.DateTimeField', [], {}), + 'blog_url': ('django.db.models.fields.CharField', [], {'max_length': '255'}), + 'book': ('django.db.models.fields.related.ForeignKey', [], {'to': "orm['forum.Book']"}), + 'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}), + 'last_edited_at': ('django.db.models.fields.DateTimeField', [], {}), + 'user': ('django.db.models.fields.related.ForeignKey', [], {'to': "orm['auth.User']"}) + }, + 'forum.bookauthorrss': { + 'Meta': {'object_name': 'BookAuthorRss', 'db_table': "u'book_author_rss'"}, + 'added_at': ('django.db.models.fields.DateTimeField', [], {}), + 'book': ('django.db.models.fields.related.ForeignKey', [], {'to': "orm['forum.Book']"}), + 'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}), + 'rss_created_at': ('django.db.models.fields.DateTimeField', [], {}), + 'title': ('django.db.models.fields.CharField', [], {'max_length': '255'}), + 'url': ('django.db.models.fields.CharField', [], {'max_length': '255'}), + 'user': ('django.db.models.fields.related.ForeignKey', [], {'to': "orm['auth.User']"}) + }, + 'forum.comment': { + 'Meta': {'object_name': 'Comment', 'db_table': "u'comment'"}, + 'added_at': ('django.db.models.fields.DateTimeField', [], {'default': 'datetime.datetime.now'}), + 'comment': ('django.db.models.fields.CharField', [], {'max_length': '300'}), + 'content_type': ('django.db.models.fields.related.ForeignKey', [], {'to': "orm['contenttypes.ContentType']"}), + 'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}), + 'object_id': ('django.db.models.fields.PositiveIntegerField', [], {}), + 'user': ('django.db.models.fields.related.ForeignKey', [], {'related_name': "'comments'", 'to': "orm['auth.User']"}) + }, + 'forum.emailfeedsetting': { + 'Meta': {'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', [], {'to': "orm['auth.User']"}) + }, + 'forum.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'}), + 'question': ('django.db.models.fields.related.ForeignKey', [], {'to': "orm['forum.Question']"}), + 'user': ('django.db.models.fields.related.ForeignKey', [], {'related_name': "'user_favorite_questions'", 'to': "orm['auth.User']"}) + }, + 'forum.flaggeditem': { + 'Meta': {'unique_together': "(('content_type', 'object_id', 'user'),)", 'object_name': 'FlaggedItem', 'db_table': "u'flagged_item'"}, + 'content_type': ('django.db.models.fields.related.ForeignKey', [], {'to': "orm['contenttypes.ContentType']"}), + 'flagged_at': ('django.db.models.fields.DateTimeField', [], {'default': 'datetime.datetime.now'}), + 'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}), + 'object_id': ('django.db.models.fields.PositiveIntegerField', [], {}), + 'user': ('django.db.models.fields.related.ForeignKey', [], {'related_name': "'flaggeditems'", 'to': "orm['auth.User']"}) + }, + 'forum.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['forum.Tag']"}), + 'user': ('django.db.models.fields.related.ForeignKey', [], {'related_name': "'tag_selections'", 'to': "orm['auth.User']"}) + }, + 'forum.question': { + 'Meta': {'object_name': 'Question', 'db_table': "u'question'"}, + 'added_at': ('django.db.models.fields.DateTimeField', [], {'default': 'datetime.datetime.now'}), + 'answer_accepted': ('django.db.models.fields.BooleanField', [], {'default': 'False', 'blank': 'True'}), + 'answer_count': ('django.db.models.fields.PositiveIntegerField', [], {'default': '0'}), + 'author': ('django.db.models.fields.related.ForeignKey', [], {'related_name': "'questions'", 'to': "orm['auth.User']"}), + 'close_reason': ('django.db.models.fields.SmallIntegerField', [], {'null': 'True', 'blank': 'True'}), + 'closed': ('django.db.models.fields.BooleanField', [], {'default': 'False', 'blank': 'True'}), + 'closed_at': ('django.db.models.fields.DateTimeField', [], {'null': 'True', 'blank': 'True'}), + 'closed_by': ('django.db.models.fields.related.ForeignKey', [], {'blank': 'True', 'related_name': "'closed_questions'", 'null': 'True', 'to': "orm['auth.User']"}), + 'comment_count': ('django.db.models.fields.PositiveIntegerField', [], {'default': '0'}), + 'deleted': ('django.db.models.fields.BooleanField', [], {'default': 'False', 'blank': '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_questions'", 'null': 'True', 'to': "orm['auth.User']"}), + 'favorited_by': ('django.db.models.fields.related.ManyToManyField', [], {'related_name': "'favorite_questions'", 'through': "'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_questions'", 'to': "orm['auth.User']"}), + 'html': ('django.db.models.fields.TextField', [], {'null': 'True'}), + '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': "'last_active_in_questions'", 'to': "orm['auth.User']"}), + '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_questions'", 'null': 'True', 'to': "orm['auth.User']"}), + 'locked': ('django.db.models.fields.BooleanField', [], {'default': 'False', 'blank': 'True'}), + 'locked_at': ('django.db.models.fields.DateTimeField', [], {'null': 'True', 'blank': 'True'}), + 'locked_by': ('django.db.models.fields.related.ForeignKey', [], {'blank': 'True', 'related_name': "'locked_questions'", 'null': 'True', 'to': "orm['auth.User']"}), + 'offensive_flag_count': ('django.db.models.fields.SmallIntegerField', [], {'default': '0'}), + 'score': ('django.db.models.fields.IntegerField', [], {'default': '0'}), + 'summary': ('django.db.models.fields.CharField', [], {'max_length': '180'}), + 'tagnames': ('django.db.models.fields.CharField', [], {'max_length': '125'}), + 'tags': ('django.db.models.fields.related.ManyToManyField', [], {'related_name': "'questions'", 'to': "orm['forum.Tag']"}), + 'text': ('django.db.models.fields.TextField', [], {'null': 'True'}), + 'title': ('django.db.models.fields.CharField', [], {'max_length': '300'}), + 'view_count': ('django.db.models.fields.PositiveIntegerField', [], {'default': '0'}), + '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', 'blank': 'True'}), + 'wikified_at': ('django.db.models.fields.DateTimeField', [], {'null': 'True', 'blank': 'True'}) + }, + 'forum.questionrevision': { + 'Meta': {'object_name': 'QuestionRevision', 'db_table': "u'question_revision'"}, + 'author': ('django.db.models.fields.related.ForeignKey', [], {'related_name': "'questionrevisions'", 'to': "orm['auth.User']"}), + 'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}), + 'question': ('django.db.models.fields.related.ForeignKey', [], {'related_name': "'revisions'", 'to': "orm['forum.Question']"}), + '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', [], {'max_length': '125'}), + 'text': ('django.db.models.fields.TextField', [], {}), + 'title': ('django.db.models.fields.CharField', [], {'max_length': '300'}) + }, + 'forum.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['forum.Question']"}), + 'when': ('django.db.models.fields.DateTimeField', [], {}), + 'who': ('django.db.models.fields.related.ForeignKey', [], {'related_name': "'question_views'", 'to': "orm['auth.User']"}) + }, + 'forum.repute': { + 'Meta': {'object_name': 'Repute', 'db_table': "u'repute'"}, + '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['forum.Question']"}), + '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']"}) + }, + 'forum.tag': { + 'Meta': {'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', 'blank': '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_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'}), + 'used_count': ('django.db.models.fields.PositiveIntegerField', [], {'default': '0'}) + }, + 'forum.validationhash': { + 'Meta': {'unique_together': "(('user', 'type'),)", 'object_name': 'ValidationHash'}, + 'expiration': ('django.db.models.fields.DateTimeField', [], {'default': 'datetime.datetime(2010, 4, 25, 19, 13, 13, 325125)'}), + 'hash_code': ('django.db.models.fields.CharField', [], {'unique': 'True', 'max_length': '255'}), + 'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}), + 'seed': ('django.db.models.fields.CharField', [], {'max_length': '12'}), + 'type': ('django.db.models.fields.CharField', [], {'max_length': '12'}), + 'user': ('django.db.models.fields.related.ForeignKey', [], {'to': "orm['auth.User']"}) + }, + 'forum.vote': { + 'Meta': {'unique_together': "(('content_type', 'object_id', 'user'),)", 'object_name': 'Vote', 'db_table': "u'vote'"}, + 'content_type': ('django.db.models.fields.related.ForeignKey', [], {'to': "orm['contenttypes.ContentType']"}), + 'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}), + 'object_id': ('django.db.models.fields.PositiveIntegerField', [], {}), + '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'}) + } + } + + complete_apps = ['forum'] diff --git a/forum/migrations/__init__.py b/forum/migrations/__init__.py new file mode 100644 index 00000000..e69de29b --- /dev/null +++ b/forum/migrations/__init__.py diff --git a/forum/models/__init__.py b/forum/models/__init__.py index 2349c9e3..d0d2d4a7 100755 --- a/forum/models/__init__.py +++ b/forum/models/__init__.py @@ -5,6 +5,8 @@ from meta import Vote, Comment, FlaggedItem from user import Activity, ValidationHash, EmailFeedSetting, AuthKeyUserAssociation from repute import Badge, Award, Repute from django.core.urlresolvers import reverse +from forum.search.indexer import create_fulltext_indexes +from django.db.models.signals import post_syncdb import re from base import * @@ -440,6 +442,7 @@ tags_updated.connect(record_update_tags, sender=Question) post_save.connect(record_favorite_question, sender=FavoriteQuestion) user_updated.connect(record_user_full_updated, sender=User) user_logged_in.connect(post_stored_anonymous_content) +#post_syncdb.connect(create_fulltext_indexes) Question = Question QuestionRevision = QuestionRevision diff --git a/forum/models/answer.py b/forum/models/answer.py index 25a885ee..3de6cfc4 100755 --- a/forum/models/answer.py +++ b/forum/models/answer.py @@ -16,6 +16,7 @@ class AnswerManager(models.Manager): author = author, added_at = added_at, wiki = wiki, + text = text, html = sanitize_html(markdowner.convert(text)), ) if answer.wiki: @@ -94,6 +95,7 @@ class Answer(Content, DeletableContent): self.last_edited_at = edited_at self.last_edited_by = edited_by self.html = sanitize_html(markdowner.convert(text)) + self.text = text #todo: bug wiki has no effect here self.save() @@ -136,9 +138,6 @@ class Answer(Content, DeletableContent): else: return None - def get_latest_revision(self): - return self.revisions.all()[0] - def get_question_title(self): return self.question.title diff --git a/forum/models/base.py b/forum/models/base.py index 52fc8522..fcec47b4 100755 --- a/forum/models/base.py +++ b/forum/models/base.py @@ -89,30 +89,31 @@ class Content(models.Model): """ Base class for Question and Answer """ - author = models.ForeignKey(User, related_name='%(class)ss') - added_at = models.DateTimeField(default=datetime.datetime.now) + author = models.ForeignKey(User, related_name='%(class)ss') + added_at = models.DateTimeField(default=datetime.datetime.now) - wiki = models.BooleanField(default=False) - wikified_at = models.DateTimeField(null=True, blank=True) + wiki = models.BooleanField(default=False) + wikified_at = models.DateTimeField(null=True, blank=True) - locked = models.BooleanField(default=False) - locked_by = models.ForeignKey(User, null=True, blank=True, related_name='locked_%(class)ss') - locked_at = models.DateTimeField(null=True, blank=True) + locked = models.BooleanField(default=False) + locked_by = models.ForeignKey(User, null=True, blank=True, related_name='locked_%(class)ss') + locked_at = models.DateTimeField(null=True, blank=True) - score = models.IntegerField(default=0) - vote_up_count = models.IntegerField(default=0) - vote_down_count = models.IntegerField(default=0) + score = models.IntegerField(default=0) + vote_up_count = models.IntegerField(default=0) + vote_down_count = models.IntegerField(default=0) - comment_count = models.PositiveIntegerField(default=0) + comment_count = models.PositiveIntegerField(default=0) offensive_flag_count = models.SmallIntegerField(default=0) - last_edited_at = models.DateTimeField(null=True, blank=True) - last_edited_by = models.ForeignKey(User, null=True, blank=True, related_name='last_edited_%(class)ss') + last_edited_at = models.DateTimeField(null=True, blank=True) + last_edited_by = models.ForeignKey(User, null=True, blank=True, related_name='last_edited_%(class)ss') - html = models.TextField() - comments = generic.GenericRelation(Comment) - votes = generic.GenericRelation(Vote) - flagged_items = generic.GenericRelation(FlaggedItem) + html = models.TextField(null=True) + text = models.TextField(null=True) #denormalized copy of latest revision + comments = generic.GenericRelation(Comment) + votes = generic.GenericRelation(Vote) + flagged_items = generic.GenericRelation(FlaggedItem) class Meta: abstract = True @@ -141,7 +142,10 @@ class Content(models.Model): self.comment_count = self.comment_count + 1 self.save() - def post_get_last_update_info(self): + def get_latest_revision(self): + return self.revisions.all()[0] + + def post_get_last_update_info(self):#todo: rename this subroutine when = self.added_at who = self.author if self.last_edited_at and self.last_edited_at > when: diff --git a/forum/models/question.py b/forum/models/question.py index 9860eb24..683f7a3c 100755 --- a/forum/models/question.py +++ b/forum/models/question.py @@ -1,28 +1,49 @@ -from base import * +from base import * #todo maybe remove * from tag import Tag +#todo: make uniform import for consts from forum.const import CONST +from forum import const from forum.utils.html import sanitize_html from markdown2 import Markdown from django.utils.html import strip_tags import datetime +from django.conf import settings +from django.utils.datastructures import SortedDict +from forum.models.tag import MarkedTag +from django.db.models import Q + markdowner = Markdown(html4tags=True) from forum.utils.lists import LazyList +#todo: too bad keys are duplicated see const sort methods +QUESTION_ORDER_BY_MAP = { + 'latest': '-added_at', + 'oldest': 'added_at', + 'active': '-last_activity_at', + 'inactive': 'last_activity_at', + 'hottest': '-answer_count', + 'coldest': 'answer_count', + 'mostvoted': '-score', + 'leastvoted': 'score', + 'relevant': None #this is a special case +} + class QuestionManager(models.Manager): def create_new(self, title=None,author=None,added_at=None, wiki=False,tagnames=None, text=None): html = sanitize_html(markdowner.convert(text)) summary = strip_tags(html)[:120] question = Question( - title = title, - author = author, - added_at = added_at, + title = title, + author = author, + added_at = added_at, last_activity_at = added_at, last_activity_by = author, - wiki = wiki, - tagnames = tagnames, - html = html, - summary = summary + wiki = wiki, + tagnames = tagnames, + html = html, + text = text, + summary = summary ) if question.wiki: question.last_edited_by = question.author @@ -39,6 +60,115 @@ class QuestionManager(models.Manager): ) return question + def run_advanced_search( + self, + request_user = None, + scope_selector = const.DEFAULT_POST_SCOPE,#unanswered/all/favorite (for logged in) + search_query = None, + tag_selector = None, + author_selector = None,#???question or answer author or just contributor + sort_method = const.DEFAULT_POST_SORT_METHOD + ): + """all parameters are guaranteed to be clean + however may not relate to database - in that case + a relvant filter will be silently dropped + """ + + qs = self.filter(deleted=False)#todo - add a possibility to see deleted questions + + #return metadata + meta_data = {} + if tag_selector: + for tag in tag_selector: + qs = qs.filter(tags__name = tag) + + if search_query: + try: + qs = qs.filter( Q(title__search = search_query) \ + | Q(text__search = search_query) \ + | Q(tagnames__search = search_query) \ + | Q(answers__text__search = search_query) + ) + except: + #fallback to dumb title match search + qs = qs.extra( + where=['title like %s'], + params=['%' + search_query + '%'] + ) + + if scope_selector: + if scope_selector == 'unanswered': + if const.UNANSWERED_MEANING == 'NO_ANSWERS': + qs = qs.filter(answer_count=0)#todo: expand for different meanings of this + elif const.UNANSWERED_MEANING == 'NO_ACCEPTED_ANSWERS': + qs = qs.filter(answer_accepted=False) + elif const.UNANSWERED_MEANING == 'NO_UPVOTED_ANSWERS': + raise NotImplementedError() + else: + raise Exception('UNANSWERED_MEANING setting is wrong') + elif scope_selector == 'favorite': + qs = qs.filter(favorited_by = request_user) + + #user contributed questions & answers + if author_selector: + try: + u = User.objects.get(id=int(author_selector)) + qs = qs.filter(Q(author=u, deleted=False) | Q(answers__author=u, answers__deleted=False)) + meta_data['author_name'] = u.username + except User.DoesNotExist: + meta_data['author_name'] = None + + #get users tag filters + if request_user and request_user.is_authenticated(): + uid_str = str(request_user.id) + #mark questions tagged with interesting tags + qs = qs.extra( + select = SortedDict([ + ( + 'interesting_score', + 'SELECT COUNT(1) FROM forum_markedtag, question_tags ' + + 'WHERE forum_markedtag.user_id = %s ' + + 'AND forum_markedtag.tag_id = question_tags.tag_id ' + + 'AND forum_markedtag.reason = \'good\' ' + + 'AND question_tags.question_id = question.id' + ), + ]), + select_params = (uid_str,), + ) + if request_user.hide_ignored_questions: + #exclude ignored tags if the user wants to + ignored_tags = Tag.objects.filter(user_selections__reason='bad', + user_selections__user = request_user) + qs = qs.exclude(tags__in=ignored_tags) + else: + #annotate questions tagged with ignored tags + qs = qs.extra( + select = SortedDict([ + ( + 'ignored_score', + 'SELECT COUNT(1) FROM forum_markedtag, question_tags ' + + 'WHERE forum_markedtag.user_id = %s ' + + 'AND forum_markedtag.tag_id = question_tags.tag_id ' + + 'AND forum_markedtag.reason = \'bad\' ' + + 'AND question_tags.question_id = question.id' + ) + ]), + select_params = (uid_str, ) + ) + # get the list of interesting and ignored tags (interesting_tag_names, ignored_tag_names) = (None, None) + pt = MarkedTag.objects.filter(user=request_user) + meta_data['interesting_tag_names'] = pt.filter(reason='good').values_list('tag__name', flat=True) + meta_data['ignored_tag_names'] = pt.filter(reason='bad').values_list('tag__name', flat=True) + + qs = qs.select_related(depth=1) + #todo: fix orderby here + orderby = QUESTION_ORDER_BY_MAP[sort_method] + if orderby: + #relevance will be ignored here + qs = qs.order_by(orderby) + qs = qs.distinct() + return qs, meta_data + def update_tags(self, question, tagnames, user): """ Updates Tag associations for a question to match the given @@ -216,6 +346,7 @@ class Question(Content, DeletableContent): self.tagnames = tags self.summary = question_summary self.html = html + self.text = text #wiki is an eternal trap whence there is no exit if self.wiki == False and wiki == True: @@ -310,9 +441,6 @@ class Question(Content, DeletableContent): def get_revision_url(self): return reverse('question_revisions', args=[self.id]) - def get_latest_revision(self): - return self.revisions.all()[0] - def get_last_update_info(self): when, who = self.post_get_last_update_info() diff --git a/forum/models/tag.py b/forum/models/tag.py index 8d26d6f4..e13baf9b 100755 --- a/forum/models/tag.py +++ b/forum/models/tag.py @@ -49,6 +49,8 @@ class TagManager(models.Manager): def get_tags_by_questions(self, questions): question_ids = [] + if len(questions) == 0: + return [] for question in questions: question_ids.append(question.id) @@ -82,4 +84,4 @@ class MarkedTag(models.Model): reason = models.CharField(max_length=16, choices=TAG_MARK_REASONS) class Meta: - app_label = 'forum'
\ No newline at end of file + app_label = 'forum' diff --git a/forum/search/README b/forum/search/README new file mode 100644 index 00000000..c15dc221 --- /dev/null +++ b/forum/search/README @@ -0,0 +1,5 @@ +module dealing with search functions +at this time only question and answer search + +that among other things contains +available full text search implementations diff --git a/forum/search/__init__.py b/forum/search/__init__.py new file mode 100644 index 00000000..e69de29b --- /dev/null +++ b/forum/search/__init__.py diff --git a/forum/search/indexer.py b/forum/search/indexer.py new file mode 100644 index 00000000..c7c45c59 --- /dev/null +++ b/forum/search/indexer.py @@ -0,0 +1,9 @@ +from django.conf import settings +from django.db import connection + +def create_fulltext_indexes(): + if settings.DATABASE_ENGINE == 'mysql': + cursor = connection.cursor() + cursor.execute('ALTER TABLE question ADD FULLTEXT (title, text, tagnames)') + cursor.execute('ALTER TABLE answer ADD FULLTEXT (title, text, tagnames)') + diff --git a/forum/search/sphinx/README b/forum/search/sphinx/README new file mode 100644 index 00000000..8c008a23 --- /dev/null +++ b/forum/search/sphinx/README @@ -0,0 +1,4 @@ +This directory contains sample configuration for sphinx search + +Sphinx is a full text search engine for MySQL (only) with full +word stemming in English and Russion (other languages are not supported) diff --git a/sphinx/sphinx.conf b/forum/search/sphinx/sphinx.conf index bf4bdc8b..bf4bdc8b 100644 --- a/sphinx/sphinx.conf +++ b/forum/search/sphinx/sphinx.conf diff --git a/forum/search/state_manager.py b/forum/search/state_manager.py new file mode 100644 index 00000000..cb1908c6 --- /dev/null +++ b/forum/search/state_manager.py @@ -0,0 +1,152 @@ +#search state manager object +#that lives in the session and takes care of the state +#persistece during the search session +from forum import const +import logging + +ACTIVE_COMMANDS = ( + 'sort', 'search', 'query', + 'reset_query', 'reset_author', 'reset_tags', + 'tags', 'scope', 'page_size', 'start_over', + 'page' +) + +def some_in(what, where): + for element in what: + if element in where: + return True + return False + +class SearchState(object): + def __init__(self): + self.scope= const.DEFAULT_POST_SCOPE + self.query = None + self.tags = None + self.author = None + self.sort = const.DEFAULT_POST_SORT_METHOD + self.page_size = const.DEFAULT_QUESTIONS_PAGE_SIZE + self.page = 1 + self.logged_in = False + logging.debug('new search state initialized') + + def __str__(self): + out = 'scope=%s\n' % self.scope + out += 'query=%s\n' % self.query + if self.tags: + out += 'tags=%s\n' % ','.join(self.tags) + out += 'author=%s\n' % self.author + out += 'sort=%s\n' % self.sort + out += 'page_size=%d\n' % self.page_size + out += 'page=%d\n' % self.page + out += 'logged_in=%s\n' % str(self.logged_in) + return out + + def set_logged_out(self): + if self.scope == 'favorite': + self.scope = None + self.logged_in = False + + def set_logged_in(self): + self.logged_in = True + + def reset(self): + #re-initialize, but keep login state + is_logged_in = self.logged_in + self.__init__() + self.logged_in = is_logged_in + + def update_value(self, key, store): + if key in store: + old_value = getattr(self, key) + new_value = store[key] + if new_value != old_value: + setattr(self, key, new_value) + self.reset_page() + + def relax_stickiness(self, input, view_log): + if view_log.get_previous(1) == 'questions': + if not some_in(ACTIVE_COMMANDS, input): + self.reset() + #todo also relax if 'all' scope was clicked twice + + def update_from_user_input(self,input,raw_input = {}): + #todo: this function will probably not + #fit the case of multiple parameters entered at the same tiem + if 'start_over' in input: + self.reset() + + if 'page' in input: + self.page = input['page'] + #special case - on page flip no other input is accepted + return + + if 'page_size' in input: + self.update_value('page_size',input) + self.reset_page()#todo may be smarter here - start with ~same q + #same as with page - return right away + return + + if 'scope' in input: + if input['scope'] == 'favorite' and self.logged_in == False: + self.reset_scope() + else: + self.update_value('scope',input) + + if 'tags' in input: + if self.tags: + old_tags = self.tags.copy() + self.tags = self.tags.union(input['tags']) + if self.tags != old_tags: + self.reset_page() + else: + self.tags = input['tags'] + + #all resets just return + if 'reset_tags' in input: + if self.tags: + self.tags = None + self.reset_page() + return + + #todo: handle case of deleting tags one-by-one + if 'reset_author' in input: + if self.author: + self.author = None + self.reset_page() + return + + if 'reset_query' in input: + self.reset_query() + return + + self.update_value('author',input) + + if 'query' in input: + self.update_value('query',input) + self.sort = 'relevant' + elif 'search' in raw_input:#a case of use nulling search query by hand + self.reset_query() + return + + + if 'sort' in input: + if input['sort'] == 'relevant' and self.query is None: + self.reset_sort() + else: + self.update_value('sort',input) + + def reset_page(self): + self.page = 1 + + def reset_query(self): + if self.query: + self.query = None + self.reset_page() + if self.sort == 'relevant': + self.reset_sort() + + def reset_sort(self): + self.sort = const.DEFAULT_POST_SORT_METHOD + + def reset_scope(self): + self.scope = const.DEFAULT_POST_SCOPE diff --git a/forum/skins/default/media/images/logo.gif b/forum/skins/default/media/images/logo.gif Binary files differindex e4d2b957..03eb79f4 100644 --- a/forum/skins/default/media/images/logo.gif +++ b/forum/skins/default/media/images/logo.gif diff --git a/forum/skins/default/media/style/style.css b/forum/skins/default/media/style/style.css index 93c979ce..3f51e619 100755 --- a/forum/skins/default/media/style/style.css +++ b/forum/skins/default/media/style/style.css @@ -204,7 +204,6 @@ blockquote { background-color: #F5F5F5; } -/*页面布局*/ #wrapper { width: 960px; margin: auto; @@ -218,7 +217,7 @@ blockquote { } #room { - padding: 10px 0 10px 0; + padding: 0 0 10px 0; background-color: #FFF; border-bottom: 1px solid #777; } @@ -251,16 +250,15 @@ blockquote { /*#licenseLogo {position:absolute;top:10px;right:10px;}*/ -/*顶部及导航栏*/ +/* why is this called top? - this contains links like login, faq, etc */ #top { position: absolute; top: 0px; - right: 0px; + right: 250px; height: 20px; text-align: right; padding: 3px; background-color: #ffffff; - width: 500px; } /*#header {width:960px;}*/ @@ -270,13 +268,24 @@ blockquote { margin-left: 20px; text-decoration: underline; font-size: 12px; - color: #333333; + color: #555555; } #logo { - padding: 5px 0px 0px 0px; + padding: 0px 0px 0px 10px; + height: 90px; + width: 70px; +} + +#logoContainer { +} +#navTabContainer { + width: 600px; + padding-left: 10px; + text-align: left; } +/* navBar includes logo, main tabs and links like logout, about, faq */ #navBar { float: clear; position: relative; @@ -285,7 +294,7 @@ blockquote { } #navBar .nav { - margin: 20px 0px 0px 16px; /*letter-spacing:1px; */ + margin: 20px 0px 0px 0px; /*letter-spacing:1px; */ } #navBar .nav a { @@ -300,8 +309,8 @@ blockquote { height: 25px; line-height: 30px; margin-left: 10px; - font-size: 14px; - font-weight: 400; + font-size: 18px; + font-weight: 100; text-decoration: none; display: block; float: left; @@ -325,7 +334,7 @@ blockquote { } #navBar .nav a.special { - font-size: 14px; + font-size: 18px; color: #B02B2C; font-weight: bold; text-decoration: none; @@ -335,35 +344,78 @@ blockquote { text-decoration: underline; } +/* todo: this is probably not used any more */ #navBar .nav div.focus { float: right; padding-right: 0px; } -/*搜索栏*/ #searchBar { - width: 958px; - background-color: #888a85; /*#e9b96e;*/ + display:inline-block; + background-color: #cccccc;/*888a85; /*#e9b96e;*/ border: 1px solid #aaaaaa; - padding: 4px 0 0 0; + padding: 4px 7px 5px 5px; } -/* #B02B2C */ -#searchBar .content { +#searchBar .searchInput { + font-size: 24px; + line-height: 24px; + height: 36px; + width: 598px; + margin: 0px; + padding: 5px 0 0 5px; } -#searchBar .searchInput { - font-size: 13px; - height: 18px; - width: 400px; +#searchBar .searchInputCancelable { + font-size: 24px; + line-height: 24px; + height: 36px; + width: 552px; + padding: 5px 0 0 5px; + margin: 0px; } #searchBar .searchBtn { - font-size: 14px; - height: 26px; - width: 80px; + font-size: 20px; + color: #666666; + height: 40px; + line-height: 22px; + text-align: center; + margin-top:1px; + padding-bottom: 4px; +} + +#searchBar .cancelSearchBtn { + font-size: 20px; + color: #666666; + height: 40px; + width: 40px; + line-height: 22px; + padding-bottom: 4px; + margin-top:1px; + text-align: center; } +#askFormBar { + display:inline-block; + background-color: #e3e3e3;/*888a85; /*#e9b96e;*/ + border: 1px solid #aaaaaa; + padding: 4px 7px 5px 5px; +} +#askFormBar p { + width: 685px; + margin:0 0 5px 0; +} +#askFormBar .questionTitleInput { + font-size: 24px; + line-height: 24px; + height: 36px; + width: 680px; + margin: 0px; + padding: 5px 0 0 5px; +} + + #searchBar .options { padding: 3px 0 3px 0; font-size: 100%; @@ -499,7 +551,7 @@ blockquote { .short-summary { position: relative; padding: 3px 5px 5px 10px; - border-top: 1px dotted #ccccce; + border-top: 1px dashed #ccccce; overflow: hidden; width: 700px; float: left; @@ -552,6 +604,10 @@ blockquote { font-weight: 800; } +.evenMore a { + text-decoration: underline; +} + .questions-count { font-size: 32px; font-family: sans-serif; @@ -623,13 +679,16 @@ blockquote { } .boxC { - background: #cacdc6; /*f9f7ed;*/ + background: white /*#cacdc6; /*f9f7ed;*/ padding: 10px; margin-bottom: 8px; + margin-left: 10px; + /* border-top: 1px solid #eeeeec; border-left: 1px solid #eeeeec; border-right: 1px solid #a9aca5; border-bottom: 1px solid #babdb6; + */ } .boxC p { @@ -846,6 +905,7 @@ a:hover.medal { width: 100%; clear: both; margin-bottom: 3px; + margin-top: 3px; } .tabsA { @@ -866,7 +926,16 @@ a:hover.medal { height: 20px; } -.tabsA a.on, .tabsA a:hover, .tabsB a.on, .tabsB a:hover { +.tabsC { + background-color: #FFF; + float: left; + position: relative; + display: block; + font-weight: bold; + height: 20px; +} + +.tabsA a.on, .tabsA a:hover, .tabsB a.on, .tabsB a:hover , .tabsC a.on, tabsC a:hover { background: #fff; color: #a40000; border-top: 1px solid #babdb6; @@ -879,7 +948,7 @@ a:hover.medal { padding: 0px 11px 0px 11px; } -.tabsA a { +.tabsA a, .tabsC a{ background: #f9f7eb; border-top: 1px solid #eeeeec; border-left: 1px solid #eeeeec; @@ -895,6 +964,12 @@ a:hover.medal { text-decoration: none; } +.tabsA .label, .tabsC .label { + float: left; + font-weight: bold; + margin: 8px 4px 0 4px; +} + .tabsB a { background: #eee; border: 1px solid #eee; @@ -920,7 +995,6 @@ a:hover.medal { } .headQuestions { - float: left; height: 23px; line-height: 23px; margin: 5px 0 0 5px; @@ -951,6 +1025,7 @@ a:hover.medal { padding-left: 24px; } +/* todo: make this class applicable to all headers it is actually uses in tags.html too */ .headUsers { float: left; height: 23px; @@ -1486,13 +1561,18 @@ span.form-error { font-size: 100%; min-height: 200px; line-height: 18px; + width: 697px; + margin:0; +} + +#id_title { width: 100%; } .wmd-preview { - margin-top: 10px; + margin: 10px 0 0 0; padding: 6px; - width: 100%; + width: 691px; background-color: #F5F5F5; min-height: 20px; } @@ -1680,7 +1760,6 @@ ins .post-tag { } .narrow .stats { - background: transparent none repeat scroll 0 0; float: left; height: 48px; margin: 0 0 0 7px; @@ -1689,6 +1768,11 @@ ins .post-tag { font-family: Arial; } +/* todo: remove this hack? */ +.user-stats-table .narrow { + width: 660px; +} + .stats div { font-size: 11px; text-align: center; @@ -2497,15 +2581,16 @@ p.signup_p { } .karma-diagram { - width:550px; - height:250px; + width:390px; + height:300px; float:left; + margin-right:10px; } .karma-details { float:right; - width:385px; - height:300px; + width:300px; + height:250px; overflow-y:auto; word-wrap:break-word; } @@ -2525,3 +2610,20 @@ p.signup_p { color:red; padding:5px; } + +.search-result-summary { + font-weight: bold; + font-size:18px; + line-height:30px; + margin:0px 0px 0px 5px; + padding:0px; +} +.search-tips { + font-size:12px; + line-height:12px; + margin:0 0 5px 5px; + padding:0px; +} +.search-tips a { + text-decoration: underline; +} diff --git a/forum/skins/default/templates/about.html b/forum/skins/default/templates/about.html index 66dcc3fd..686141b3 100644 --- a/forum/skins/default/templates/about.html +++ b/forum/skins/default/templates/about.html @@ -1,4 +1,4 @@ -{% extends "base_content.html" %} +{% extends "base.html" %} <!-- template about.html --> {% load i18n %} {% load extra_tags %} diff --git a/forum/skins/default/templates/ask.html b/forum/skins/default/templates/ask.html index 083b01d9..4278f4cb 100644 --- a/forum/skins/default/templates/ask.html +++ b/forum/skins/default/templates/ask.html @@ -56,6 +56,7 @@ </script> {% endblock %} +{% comment %} {% block content %} <div id="main-bar" class="headNormal"> {% trans "Ask a question" %} @@ -124,6 +125,7 @@ </div> </div> {% endblock %} +{% endcomment %} {% block sidebar %} {% include "question_edit_tips.html" %} diff --git a/forum/skins/default/templates/ask_form.html b/forum/skins/default/templates/ask_form.html new file mode 100644 index 00000000..25e9fe6c --- /dev/null +++ b/forum/skins/default/templates/ask_form.html @@ -0,0 +1,66 @@ +{% load i18n %} +{% load smart_if %} +<div id="askform"> + <form id="fmask" action="" method="post" > + <div class="form-item"> + {% comment %} + <label for="id_title" ><strong>{{ form.title.label_tag }}:</strong></label> + {% endcomment %} + <div id="askFormBar"> + {% if not request.user.is_authenticated %} + <p>{% trans "login to post question info" %}</p> + {% else %} + {% ifequal settings.EMAIL_VALIDATION 'on' %} + {% if not request.user.email_isvalid %} + {% blocktrans with request.user.email as email %}must have valid {{email}} to post, + see {{email_validation_faq_url}} + {% endblocktrans %} + {% endif %} + {% endifequal %} + {% endif %} + <input id="id_title" class="questionTitleInput" name="title" + value="{% if form.initial.title %}{{form.initial.title}}{% endif %}"/> + </div> + {{ form.title.errors }} + <span class="form-error"></span><br/> + <div class="title-desc"> + {{ form.title.help_text }} + </div> + </div> + + <div class="form-item"> + <div id="wmd-button-bar" class="wmd-panel"></div> + {{ form.text }} + + <div class="preview-toggle"> + <table> + <tr> + <td> + <span id="pre-collapse" title="{% trans "Toggle the real time Markdown editor preview" %}">{% trans "toggle preview" %}</span> + </td> + {% if settings.WIKI_ON %} + <td style="text-align:right;"> + {{ form.wiki }} <span style="font-weight:normal;cursor:help" title="{{form.wiki.help_text}}">{{ form.wiki.label_tag }} </span> + </td> + {% endif %} + </tr> + + </table> + </div> + <div id="previewer" class="wmd-preview"></div> + <span class="form-error"></span> + </div> + <div class="form-item"> + <strong>{{ form.tags.label_tag }}:</strong> {% trans "(required)" %} <span class="form-error"></span><br/> + {{ form.tags }} {{ form.tags.errors }} + </div> + <p class="title-desc"> + {{ form.tags.help_text }} + </p> + {% if not request.user.is_authenticated %} + <input type="submit" value="{% trans "Login/signup to post your question" %}" class="submit" /> + {% else %} + <input type="submit" value="{% trans "Ask your question" %}" class="submit" /> + {% endif %} + </form> +</div> diff --git a/forum/skins/default/templates/base.html b/forum/skins/default/templates/base.html index 1018da50..0b85e7fb 100644 --- a/forum/skins/default/templates/base.html +++ b/forum/skins/default/templates/base.html @@ -2,6 +2,7 @@ <!-- template base.html --> {% load extra_filters %} {% load extra_tags %} +{% load smart_if %} {% load i18n %} <html xmlns="http://www.w3.org/1999/xhtml"> <head> @@ -36,7 +37,19 @@ }); </script> {% endif %} - + {% if active_tab != "tags" and active_tab != "users" %} + <script type="text/javascript"> + $('#nav_ask').click( + function(){ + alert('hullo'); + var starting_title = $('#keywords').attr('value'); + alert('tittle is ' + starting_title); + window.location.href = $(this).attr('href') + '?' + + starting_title; + } + ); + </script> + {% endif %} {% block forejs %} {% endblock %} </head> @@ -55,6 +68,7 @@ <div id="wrapper"> <div id="room"> <div id="CALeft"> + {% include "input_bar.html" %} {% block content%} {% endblock%} diff --git a/forum/skins/default/templates/base_content.html b/forum/skins/default/templates/base_content.html index 1bae0afd..284007d8 100644 --- a/forum/skins/default/templates/base_content.html +++ b/forum/skins/default/templates/base_content.html @@ -55,6 +55,7 @@ <div id="wrapper"> <div id="room"> <div id="CAFull"> + {% include "input_bar.html" %} {% block content%} {% endblock%} diff --git a/forum/skins/default/templates/book.html b/forum/skins/default/templates/book.html index 8574fa73..528b800d 100644 --- a/forum/skins/default/templates/book.html +++ b/forum/skins/default/templates/book.html @@ -122,7 +122,7 @@ </h3> <div class="tags"> {% for tag in question.tagname_list %} - <a href="{% url tag_questions tag|urlencode %}" title="{% "see questions tagged with" %}'{{ tag }}'{% trans "using tags" %}" rel="tag">{{ tag }}</a> + <a href="{% url questions %}?tags={{tag|urlencode}}" title="{% blocktrans %}see questions tagged '{{ tag }}'{% endblocktrans %}" rel="tag">{{ tag }}</a> {% endfor %} </div> <div class="started"> diff --git a/forum/skins/default/templates/faq.html b/forum/skins/default/templates/faq.html index ca963237..cc790ccc 100644 --- a/forum/skins/default/templates/faq.html +++ b/forum/skins/default/templates/faq.html @@ -1,4 +1,4 @@ -{% extends "base_content.html" %} +{% extends "base.html" %} <!-- template faq.html --> {% load extra_tags %} {% load humanize %} diff --git a/forum/skins/default/templates/feedback.html b/forum/skins/default/templates/feedback.html index 38bb48ff..af4f635f 100644 --- a/forum/skins/default/templates/feedback.html +++ b/forum/skins/default/templates/feedback.html @@ -1,4 +1,4 @@ -{% extends "base_content.html" %} +{% extends "base.html" %} <!-- template about.html --> {% load i18n %} {% load extra_tags %} diff --git a/forum/skins/default/templates/header.html b/forum/skins/default/templates/header.html index 099bfb85..0a1a3296 100644 --- a/forum/skins/default/templates/header.html +++ b/forum/skins/default/templates/header.html @@ -1,5 +1,6 @@ <!-- template header.html --> {% load extra_tags %} +{% load smart_if %} {% load i18n %} <div id="roof"> <div id="navBar"> @@ -13,53 +14,34 @@ <a href="{% url about %}">{% trans "about" %}</a> <a href="{% url faq %}">{% trans "faq" %}</a> </div> - <table width="100%" border="0" cellspacing="0" cellpadding="0"> + <table border="0" cellspacing="0" cellpadding="0"> <tr> - <td width="23%"> - <div id="logo"> - <a href="{% url index %}"> - <img src="{% media "/media/images/logo.png" %}" title="{% trans "back to home page" %}" alt="{{settings.APP_TITLE}} logo"/> - </a> - </div> - </td> - <td width="77%" valign="bottom"> - <div class="nav"> - <a id="nav_questions" href="{% url questions %}" >{% trans "questions" %}</a> - <a id="nav_tags" href="{% url tags %}">{% trans "tags" %}</a> - <a id="nav_users" href="{% url users %}">{% trans "users" %}</a> - {% if settings.BOOKS_ON %} - <a id="nav_books" href="{% url books %}">{% trans "books" %}</a> - {% endif %} - <a id="nav_badges" href="{% url badges %}">{% trans "badges" %}</a> - <a id="nav_unanswered" href="{% url unanswered %}">{% trans "unanswered questions" %}</a> - <div class="focus"> - <a id="nav_ask" href="{% url ask %}" class="special">{% trans "ask a question" %}</a> - </div> + <td id="logoContainer"> + <div id="logo"> + <a href="{% url questions %}?start_over=true"><img + src="{% media "/media/images/logo.gif" %}" title="{% trans "back to home page" %}" alt="{{settings.APP_TITLE}} logo"/></a> + </div> + </td> + <td id="navTabContainer" valign="bottom" align="left"> + <div class="nav"> + <a id="nav_questions" href="{% url questions %}" >{% trans "questions" %}</a> + <a id="nav_tags" href="{% url tags %}">{% trans "tags" %}</a> + <a id="nav_users" href="{% url users %}">{% trans "users" %}</a> + {% if settings.BOOKS_ON %} + <a id="nav_books" href="{% url books %}">{% trans "books" %}</a> + {% endif %} + <a id="nav_badges" href="{% url badges %}">{% trans "badges" %}</a> + <a id="nav_ask" href="{% url ask %}" class="special">{% trans "ask a question" %}</a> + {% comment %} + <a id="nav_unanswered" href="{% url unanswered %}">{% trans "unanswered questions" %}</a> + <div class="focus"> + <a id="nav_ask" href="{% url ask %}" class="special">{% trans "ask a question" %}</a> </div> - - </td> + {% endcomment %} + </div> + </td> </tr> </table> </div> - <div id="searchBar"> - <table width="100%" border="0" cellpadding="0" cellspacing="0" class="content"> - <tr> - <td align="center" valign="middle"> - <form action="{% url search %}" method="get"> - <div> - <input type="text" class="searchInput" value="{{ keywords }}" name="q" id="keywords" /> - <input type="submit" name="Submit" value="{% trans "search" %}" class="searchBtn" /> - </div> - <div class="options"> - <input id="type-question" type="radio" value="question" name="t" - checked="checked" /><label for="type-question">{% trans "questions" %}</label> - <input id="type-tag" type="radio" value="tag" name="t" /><label for="type-tag">{% trans "tags" %}</label> - <input id="type-user" type="radio" value="user" name="t" /><label for="type-user">{% trans "users" %}</label> - </div> - </form> - </td> - </tr> - </table> - </div> </div> <!-- end template header.html --> diff --git a/forum/skins/default/templates/index.html b/forum/skins/default/templates/index.html index 8a885dd4..f94f84fc 100644 --- a/forum/skins/default/templates/index.html +++ b/forum/skins/default/templates/index.html @@ -23,7 +23,7 @@ {% endblock %}
{% block content %}
<div class="tabBar">
- <div class="headQuestions">{% trans "Questions" %}</div>
+ <div class="headUsers">{% trans "Questions" %}</div>
<div class="tabsA">
<a id="latest" href="{% url questions %}?sort=latest" title="{% trans "last updated questions" %}" >{% trans "newest" %}</a>
<a id="hottest" href="{% url questions %}?sort=hottest" title="{% trans "hottest questions" %}" >{% trans "hottest" %}</a>
@@ -57,11 +57,12 @@ {% cache 60 recent_tags %}
{% for tag in tags %}
<a rel="tag"
- title="{% blocktrans with tag.name as tagname %}see questions tagged '{{tagname}}'{% endblocktrans %}" href="{% url tag_questions tag.name|urlencode %}">{{ tag.name }}</a>
+ title="{% blocktrans with tag.name as tagname %}see questions tagged '{{tagname}}'{% endblocktrans %}"
+ href="{% url questions %}?tags={{tag.name|urlencode}}">{{ tag.name }}</a>
{% endfor %}
{% endcache %}
</div>
- <div class="more"><a href="{% url tags %}">{% trans "popular tags" %} </a> </div>
+ <div class="more"><a href="{% url tags %}">{% trans "see all tags" %}</a> </div>
</div>
</div>
{% if awards %}
diff --git a/forum/skins/default/templates/index_.html b/forum/skins/default/templates/index_.html index 5e4cf533..36531f62 100644 --- a/forum/skins/default/templates/index_.html +++ b/forum/skins/default/templates/index_.html @@ -22,7 +22,7 @@ {% endblock %}
{% block content %}
<div class="tabBar">
- <div class="headQuestions">{% trans "Questions" %}</div>
+ <div class="headUsers">{% trans "Questions" %}</div>
<div class="tabsA">
<a id="latest" href="{% url index %}?sort=latest" title="{% trans "last updated questions" %}" >{% trans "newest" %}</a>
<a id="hottest" href="{% url index %}?sort=hottest" title="{% trans "hottest questions" %}" >{% trans "hottest" %}</a>
@@ -60,7 +60,7 @@ <div class="tags">
{% for tag in question.tagname_list %}
- <a href="{% url tag_questions tag|urlencode %}" title="{% trans "see questions tagged" %} '{{ tag }}' {% trans "using tags" %}" rel="tag">{{ tag }}</a>
+ <a href="{% url questions %}?tags={{tag|urlencode}}" title="{% blocktrans %}see questions tagged '{{ tag }}'{% endblocktrans %}" rel="tag">{{ tag }}</a>
{% endfor %}
</div>
</div>
@@ -87,7 +87,8 @@ <div class="tags">
{% for tag in tags %}
<a rel="tag"
- title="{% blocktrans with tag.name as tagname %}see questions tagged '{{tagname}}'{% endblocktrans %}" href="{% url tag_questions tag.name|urlencode %}">{{ tag.name }}</a>
+ title="{% blocktrans with tag.name as tagname %}see questions tagged '{{tagname}}'{% endblocktrans %}"
+ href="{% url questions %}?tags={{tag.name|urlencode}}">{{ tag.name }}</a>
{% endfor %}
</div>
<div class="more"><a href="{% url tags %}">{% trans "popular tags" %} »</a> </div>
diff --git a/forum/skins/default/templates/input_bar.html b/forum/skins/default/templates/input_bar.html new file mode 100644 index 00000000..59236350 --- /dev/null +++ b/forum/skins/default/templates/input_bar.html @@ -0,0 +1,45 @@ +{% load i18n %} +{% load smart_if %} +{% if active_tab != "ask" %} +<div id="searchBar"> + {% comment %}url action depends on which tab is active{% endcomment %} + <form + {% if active_tab == "tags" or active_tab == "users" %} + action="{% url search %}" + {% else %} + action="{% url questions %}" + {% endif %} + method="get"> + {% comment %} class was searchInput {% endcomment %} + <input + {% if query %} + class="searchInputCancelable" + {% else %} + class="searchInput" + {% endif %} + type="text" + value="{{ query|default_if_none:"" }}" + name="query" + id="keywords"/> + {% if query %}{% comment %}query is only defined by questions view{% endcomment %} + <input type="button" + value="x" + name="reset_query" + {% comment %}todo - make sure it works on Enter keypress{% endcomment %} + onclick="window.location.href='{% url questions %}?reset_query=true'" + value="true" + class="cancelSearchBtn"/> + {% endif %} + <input type="submit" value="{% trans "search" %}" name="search" class="searchBtn" default /> + {% if active_tab == "tags" %} + <input type="hidden" name="t" value="tag"/> + {% else %} + {% if active_tab == "users" %} + <input type="hidden" name="t" value="user"/> + {% endif %} + {% endif %} + </form> +</div> +{% else %} + {% include "ask_form.html" %} +{% endif %} diff --git a/forum/skins/default/templates/question.html b/forum/skins/default/templates/question.html index 1c542c8b..79ff9a5b 100644 --- a/forum/skins/default/templates/question.html +++ b/forum/skins/default/templates/question.html @@ -128,10 +128,12 @@ {{ question.html|safe }}
</div>
<div id="question-controls" class="post-controls">
+ {% comment %}todo: here we have important case to reset search state{% endcomment %}
<div id="question-tags" class="tags">
{% for tag in question.tagname_list %}
- <a href="{% url tag_questions tag|urlencode %}" class="post-tag"
- title="{% blocktrans with tag as tagname %}see questions tagged '{{ tagname }}'{% endblocktrans %}" rel="tag">{{ tag }}</a>
+ <a href="{% url questions %}?tags={{tag|urlencode}}&start_over=true"
+ class="post-tag"
+ title="{% blocktrans %}see questions tagged '{{tag}}'{% endblocktrans %}" rel="tag">{{ tag }}</a>
{% endfor %}
</div>
{% joinitems using '<span class="action-link-separator">|</span>' %}
@@ -224,7 +226,7 @@ <hr/>
<div class="tabBar">
<a name="sort-top"></a>
- <div class="headQuestions">
+ <div class="headUsers">
{% blocktrans count answers|length as counter %}
One Answer:
{% plural %}
@@ -474,9 +476,10 @@ </p>
<p class="tags" >
{% for tag in tags %}
- <a href="{% url tag_questions tag.name|urlencode %}"
- title="{% trans "see questions tagged"%}'{{tag.name}}'{% trans "using tags" %}"
- rel="tag">{{ tag.name }}</a> <span class="tag-number">×{{ tag.used_count|intcomma }}</span><br/>
+ <a href="{% url questions %}?tags={{tag.name|urlencode}}&start_over=true"
+ title="{% blocktrans with tag.name as tag_name %}see questions tagged '{{tag_name}}'{% endblocktrans %}"
+ rel="tag">{{ tag.name }}</a>
+ <span class="tag-number">×{{ tag.used_count|intcomma }}</span><br/>
{% endfor %}
</p>
<p>
diff --git a/forum/skins/default/templates/question_list.html b/forum/skins/default/templates/question_list.html index 53633691..38ac254a 100644 --- a/forum/skins/default/templates/question_list.html +++ b/forum/skins/default/templates/question_list.html @@ -16,7 +16,7 @@ </div>
<div class="tags">
{% for tag in question.tagname_list %}
- <a href="{% url tag_questions tag|urlencode %}" title="{% trans "see questions tagged" %} '{{ tag }}' {% trans "using tags" %}" rel="tag">{{ tag }}</a>
+ <a href="{% url questions %}?tags={{tag|urlencode}}" title="{% blocktrans %}see questions tagged '{{ tag }}'{%endblocktrans %}" rel="tag">{{ tag }}</a>
{% endfor %}
</div>
</div>
diff --git a/forum/skins/default/templates/question_summary_list_roll.html b/forum/skins/default/templates/question_summary_list_roll.html index 57685d6d..f2432a24 100644 --- a/forum/skins/default/templates/question_summary_list_roll.html +++ b/forum/skins/default/templates/question_summary_list_roll.html @@ -49,7 +49,7 @@ <div class="tags"> {% for tag in question.tagname_list %} - <a href="{% url tag_questions tag|urlencode %}" title="{% trans "see questions tagged" %}'{{ tag }}'{% trans "using tags" %}" rel="tag">{{ tag }}</a> + <a href="{% url questions %}?tags={{tag|urlencode}}" title="{% blocktrans %}see questions tagged '{{ tag }}'{% endblocktrans %}" rel="tag">{{ tag }}</a> {% endfor %} </div> </div> diff --git a/forum/skins/default/templates/questions.html b/forum/skins/default/templates/questions.html index 366727d1..f864180f 100644 --- a/forum/skins/default/templates/questions.html +++ b/forum/skins/default/templates/questions.html @@ -10,9 +10,11 @@ <script type="text/javascript">
var tags = {{ tags_autocomplete|safe }};
$().ready(function(){
- var tab_id = "{{ tab_id }}";
- $("#"+tab_id).attr('className',"on");
- var on_tab = {% if is_unanswered %}'#nav_unanswered'{% else %}'#nav_questions'{% endif %};
+ var sort_tab_id = "{{ sort }}";
+ $("#"+sort_tab_id).attr('className',"on");
+ var scope_tab_id = "{{ scope }}";
+ $("#"+scope_tab_id).attr('className',"on");
+ var on_tab = '#nav_questions';
$(on_tab).attr('className','on');
Hilite.exact = false;
Hilite.elementid = "listA";
@@ -24,7 +26,8 @@ {% endblock %}
{% block content %}
<div class="tabBar">
- <div class="headQuestions">
+ {% comment %}
+ <div class="headUsers">
{% if searchtag %}
{% trans "Found by tags" %}
{% else %}
@@ -42,75 +45,197 @@ {% endif %}
{% endif %}
{% endif %}
+ </div><br/>
+ {% endcomment %}
+ <div class="tabsC">
+ <span class="label">{% trans "In:" %}</span>
+ <a id="all" class="off" href="?scope=all" title="{% trans "see all questions" %}">{% trans "all" %}</a>
+ <a id="unanswered" class="off" href="?scope=unanswered&sort=coldest" title="{% trans "see unanswered questions" %}">{% trans "unanswered" %}</a>
+ {% if request.user.is_authenticated %}
+ <a id="favorite" class="off" href="?scope=favorite" title="{% trans "see your favorite questions" %}">{% trans "favorite" %}</a>
+ {% endif %}
</div>
<div class="tabsA">
- <a id="latest" href="{% if is_search %}{{ search_uri }}&{% else %}?{% endif %}sort=latest" class="off" title="{% trans "most recently asked questions" %}">{% trans "newest" %}</a>
- <a id="active" href="{% if is_search %}{{ search_uri }}&{% else %}?{% endif %}sort=active" class="off" title="{% trans "most recently updated questions" %}">{% trans "active" %}</a>
- <a id="hottest" href="{% if is_search %}{{ search_uri }}&{% else %}?{% endif %}sort=hottest" class="off" title="{% trans "hottest questions" %}">{% trans "hottest" %}</a>
- <a id="mostvoted" href="{% if is_search %}{{ search_uri }}&{% else %}?{% endif %}sort=mostvoted" class="off" title="{% trans "most voted questions" %}">{% trans "most voted" %}</a>
+ <span class="label">{% trans "Sort by:" %}</span>
+ {% if sort == "oldest" %}
+ <a id="oldest"
+ href="?sort=latest"
+ class="off"
+ title="{% trans "click to see the newest questions" %}">{% trans "oldest" %}</a>
+ {% else %}
+ {% if sort == "latest" %}
+ <a id="latest"
+ href="?sort=oldest"
+ class="off"
+ title="{% trans "click to see the oldest questions" %}">{% trans "newest" %}</a>
+ {% else %}
+ <a id="latest"
+ href="?sort=latest"
+ class="off"
+ title="{% trans "click to see the newest questions" %}">{% trans "newest" %}</a>
+ {% endif %}
+ {% endif %}
+
+ {% if sort == "inactive" %}
+ <a id="inactive"
+ href="?sort=active"
+ class="off"
+ title="{% trans "click to see the most recently updated questions" %}">{% trans "inactive" %}</a>
+ {% else %}
+ {% if sort == "active" %}
+ <a id="active"
+ href="?sort=inactive"
+ class="off"
+ title="{% trans "click to see the least recently updated questions" %}">{% trans "active" %}</a>
+ {% else %}
+ <a id="active"
+ href="?sort=active"
+ class="off"
+ title="{% trans "click to see the most recently updated questions" %}">{% trans "active" %}</a>
+ {% endif %}
+ {% endif %}
+
+ {% if sort == "coldest" %}
+ <a id="coldest"
+ href="?sort=hottest"
+ class="off"
+ title="{% trans "click to see hottest questions" %}">{% trans "less answers" %}</a>
+ {% else %}
+ {% if sort == "hottest" %}
+ <a id="hottest"
+ href="?sort=coldest"
+ class="off"
+ title="{% trans "click to see coldest questions" %}">{% trans "more answers" %}</a>
+ {% else %}
+ <a id="hottest"
+ href="?sort=hottest"
+ class="off"
+ title="{% trans "click to see hottest questions" %}">{% trans "more answers" %}</a>
+ {% endif %}
+ {% endif %}
+
+ {% if sort == "leastvoted" %}
+ <a id="leastvoted"
+ href="?sort=mostvoted"
+ class="off"
+ title="{% trans "click to see most voted questions" %}">{% trans "unpopular" %}</a>
+ {% else %}
+ {% if sort == "mostvoted" %}
+ <a id="mostvoted"
+ href="?sort=leastvoted"
+ class="off"
+ title="{% trans "click to see least voted questions" %}">{% trans "popular" %}</a>
+ {% else %}
+ <a id="mostvoted"
+ href="?sort=mostvoted"
+ class="off"
+ title="{% trans "click to see most voted questions" %}">{% trans "popular" %}</a>
+ {% endif %}
+ {% endif %}
</div>
</div>
+{% if questions_count > 0 %}
+ <div style="clear:both">
+ <p class="search-result-summary">
+ {% if author_name or search_tags or query %}
+ {% blocktrans count questions_count as cnt with questions_count|intcomma as q_num %} One question found{% plural %}{{q_num}} questions found{% endblocktrans %}
+ {% else %}
+ {% blocktrans count questions_count as cnt with questions_count|intcomma as q_num %} {{q_num}} question{% plural %}{{q_num}} questions{% endblocktrans %}
+ {% endif %}
+ {% joinitems using ', ' %}
+ {% if author_name %}
+ {% blocktrans %}with {{author_name}}'s contributions{% endblocktrans %}
+ {% endif %}
+ {% separator %}
+ {% if search_tags %}
+ {% trans "tagged" %}
+ "{{ search_tags|join:"\", \"" }}"
+ {% endif %}
+ {% endjoinitems %}
+ </p>
+ {% if author_name or search_tags or query %}
+ <p class="search-tips">{% trans "Search tips:" %}
+ {% ifmany query search_tags author_name %}
+ {% joinitems using ', ' ' or ' %}
+ {% if author_name %}
+ <a href="{% url questions %}?reset_author=true">{% trans "reset author" %}</a>
+ {% endif %}
+ {% separator %}
+ {% if search_tags %}
+ <a href="{% url questions %}?reset_tags=true">{% trans "reset tags" %}</a>
+ {% endif %}
+ {% separator %}
+ {% ifmany query search_tags author_name %}
+ <a href="{% url questions %}?start_over=true">{% trans "start over" %}</a>
+ {% endifmany %}
+ {% endjoinitems %}
+ {% else %}
+ <a href="{% url questions %}?start_over=true">{% trans "start over" %}</a>
+ {% endifmany %}
+ {% trans " - to expand, or dig in by adding more tags and revising the query." %}
+ </p>
+ {% else %}
+ <p class="search-tips">{% trans "Search tip:" %} {% trans "add tags and a query to focus your search" %}</p>
+ {% endif %}
+
+ </div>
+{% endif %}
<div id="listA">
{% include "question_list.html" %}
- {% if searchtitle %}
+ {% comment %}todo: fix css here{% endcomment %}
{% if questions_count == 0 %}
- <p class="evenMore" style="padding-top:30px;text-align:center;">
- {% trans "Did not find anything?" %}
+ {% comment %}todo: add tips to widen selection{% endcomment%}
+ <p class="evenMore" style="padding-top:30px;text-align:center;">
+ {% if scope == "unanswered" %}
+ {% trans "There are no unanswered questions here" %}
+ {% endif %}
+ {% if scope == "favorite" %}
+ {% trans "No favorite questions here. " %}
+ {% trans "Please start (bookmark) some questions when you visit them" %}
+ {% endif %}
+ </p>
+ {% if query or search_tags or author_name %}
+ <p class="evenMore" style="text-align:center">
+ {% trans "You can expand your search by " %}
+ {% ifmany query search_tags author_name %}
+ {% joinitems using ', ' ' or ' %}
+ {% if author_name %}
+ <a href="{% url questions %}?reset_author=true">{% trans "resetting author" %}</a>
+ {% endif %}
+ {% separator %}
+ {% if search_tags %}
+ <a href="{% url questions %}?reset_tags=true">{% trans "resetting tags" %}</a>
+ {% endif %}
+ {% separator %}
+ {% ifmany query search_tags author_name %}
+ <a href="{% url questions %}?start_over=true">{% trans "starting over" %}</a>
+ {% endifmany %}
+ {% endjoinitems %}
+ {% else %}
+ <a href="{% url questions %}?start_over=true">{% trans "starting over" %}</a>
+ {% endifmany %}
+ </p>
+ {% endif %}
+ <p class="evenMore" style="text-align:center">
+ <a href="{% url ask %}">{% trans "Please always feel free to ask your question!" %}</a>
+ </p>
{% else %}
- <p class="evenMore" style="padding-left:9px">
- {% trans "Did not find what you were looking for?" %}
+ <p class="evenMore" style="padding-left:9px">
+ {% trans "Did not find what you were looking for?" %}
+ <a href="{% url ask %}">{% trans "Please, post your question!" %}</a>
+ </p>
{% endif %}
- <a href="{% url ask %}">{% trans "Please, post your question!" %}</a>
- </p>
- {% endif %}
</div>
{% endblock %}
-{% block tail %}
- <div class="pager">{% cnprog_paginator context %}</div>
- <div class="pagesize">{% cnprog_pagesize context %}</div>
-{% endblock %}
+ {% block tail %}
+ {% if questions_count > 10 %}{%comment%}todo: remove magic number{%endcomment%}
+ <div class="pager">{% cnprog_paginator context %}</div>
+ <div class="pagesize">{% cnprog_pagesize context %}</div>
+ {% endif %}
+ {% endblock %}
{% block sidebar %}
-<div class="boxC">
- {% if searchtag %}
- {% blocktrans count questions_count as cnt with questions_count|intcomma as q_num and searchtag as tagname %}have total {{q_num}} questions tagged {{tagname}}{% plural %}have total {{q_num}} questions tagged {{tagname}}{% endblocktrans %}
- {% else %}
- {% if searchtitle %}
- {% if settings.USE_SPHINX_SEARCH %}
- {% blocktrans count questions_count as cnt with questions_count|intcomma as q_num %} have total {{q_num}} questions containing {{searchtitle}} in full text {% plural %} have total {{q_num}} questions containing {{searchtitle}} in full text {% endblocktrans %}
- {% else %}
- {% blocktrans count questions_count as cnt with questions_count|intcomma as q_num %} have total {{q_num}} questions containing {{searchtitle}} {% plural %} have total {{q_num}} questions containing {{searchtitle}} {% endblocktrans %}
- {% endif %}
- {% else %}
- {% if is_unanswered %}
- {% blocktrans count questions as cnt with questions_count|intcomma as q_num %} have total {{q_num}} unanswered questions {% plural %} have total {{q_num}} unanswered questions {% endblocktrans %}
- {% else %}
- {% blocktrans count questions as cnt with questions_count|intcomma as q_num %} have total {{q_num}} questions {% plural %} have total {{q_num}} questions {% endblocktrans %}
- {% endif %}
- {% endif %}
- {% endif %}
- <p class="nomargin">
- {% ifequal tab_id "latest" %}
- {% trans "latest questions info" %}
- {% endifequal %}
-
- {% ifequal tab_id "active" %}
- {% trans "Questions are sorted by the <strong>time of last update</strong>." %}
- {% trans "Most recently answered ones are shown first." %}
- {% endifequal %}
-
- {% ifequal tab_id "hottest" %}
- {% trans "Questions sorted by <strong>number of responses</strong>." %}
- {% trans "Most answered questions are shown first." %}
- {% endifequal %}
-
- {% ifequal tab_id "mostvoted" %}
- {% trans "Questions are sorted by the <strong>number of votes</strong>." %}
- {% trans "Most voted questions are shown first." %}
- {% endifequal %}
- </p>
-</div>
{% if request.user.is_authenticated %}
{% include "tag_selector.html" %}
{% endif %}
@@ -118,7 +243,7 @@ <h3 class="subtitle">{% trans "Related tags" %}</h3>
<div class="tags">
{% for tag in tags %}
- <a rel="tag" title="{% blocktrans with tag.name as tag_name %}see questions tagged '{{ tag_name }}'{% endblocktrans %}" href="{% url tag_questions tag.name|urlencode %}">{{ tag.name }}</a>
+ <a rel="tag" title="{% blocktrans with tag.name as tag_name %}see questions tagged '{{ tag_name }}'{% endblocktrans %}" href="{% url questions %}?tags={{tag.name|urlencode}}">{{ tag.name }}</a>
<span class="tag-number">× {{ tag.used_count|intcomma }}</span>
<br />
{% endfor %}
diff --git a/forum/skins/default/templates/tag_selector.html b/forum/skins/default/templates/tag_selector.html index 5e3e2ad8..85b858d2 100644 --- a/forum/skins/default/templates/tag_selector.html +++ b/forum/skins/default/templates/tag_selector.html @@ -1,5 +1,6 @@ {% load i18n %} {% load extra_tags %} +{% comment %}todo - maybe disable navigation from ignored tags here when "hide" is on - with js?{%endcomment%} <div id="tagSelector" class="boxC"> <h3 class="subtitle">{% trans "Interesting tags" %}</h3> <div class="tags interesting marked-tags"> @@ -7,8 +8,8 @@ {% spaceless %} <span class="deletable-tag" id="interesting-tag-{{tag_name}}"> <a rel="tag" - title="{% blocktrans with tag as tagname %}see questions tagged '{{ tag_name }}'{% endblocktrans %}" - href="{% url tag_questions tag_name|urlencode %}">{{tag_name}}</a> + title="{% blocktrans %}see questions tagged '{{ tag_name }}'{% endblocktrans %}" + href="{% url questions %}?tags={{tag_name|urlencode}}">{{tag_name}}</a> <img class="delete-icon" src="{% media "/media/images/close-small-dark.png" %}" title="{% blocktrans %}remove '{{tag_name}}' from the list of interesting tags{% endblocktrans %}"/> @@ -24,8 +25,8 @@ {% spaceless %} <span class="deletable-tag" id="ignored-tag-{{tag_name}}"> <a rel="tag" - title="{% blocktrans with tag as tagname %}see questions tagged '{{ tag_name }}'{% endblocktrans %}" - href="{% url tag_questions tag_name|urlencode %}">{{tag_name}}</a> + title="{% blocktrans %}see questions tagged '{{ tag_name }}'{% endblocktrans %}" + href="{% url questions %}?tags={{tag_name|urlencode}}">{{tag_name}}</a> <img class="delete-icon" src="{% media "/media/images/close-small-dark.png" %}" title="{% blocktrans %}remove '{{tag_name}}' from the list of ignored tags{% endblocktrans %}"/> diff --git a/forum/skins/default/templates/tags.html b/forum/skins/default/templates/tags.html index 50f90fb1..6627db32 100644 --- a/forum/skins/default/templates/tags.html +++ b/forum/skins/default/templates/tags.html @@ -1,4 +1,4 @@ -{% extends "base_content.html" %} +{% extends "base.html" %} <!-- tags.html --> {% load i18n %} {% load extra_tags %} @@ -27,7 +27,7 @@ {% block content %} <!-- Tabs --> <div class="tabBar"> - <div class="headQuestions">{% trans "Tag list" %}</div> + <div class="headUsers">{% trans "Tag list" %}</div> <div class="tabsA"> <a id="sort_name" href="{% url tags %}?sort=name" class="off" title="{% trans "sorted alphabetically" %}">{% trans "by name" %}</a> <a id="sort_used" href="{% url tags %}?sort=used" class="off" title="{% trans "sorted by frequency of tag use" %}">{% trans "by popularity" %}</a> @@ -36,7 +36,7 @@ <div id="searchtags"> <p> {% if stag %} - {% trans "All tags matching query" %} '<span class="darkred"><strong>{{ stag }}</strong></span>' {% trans "all tags - make this empty in english" %}: + {% blocktrans %}All tags matching '<span class="darkred"><strong>{{ stag }}</strong></span>'{% endblocktrans %}: {% endif %} {% if not tags.object_list %} <span>{% trans "Nothing found" %}</span> @@ -46,7 +46,8 @@ <ul class="tagsList tags"> {% for tag in tags.object_list %} <li> - <a href="{% url tag_questions tag|urlencode %}" title="{% trans "see questions tagged" %}'{{ tag }}'{% trans "using tags" %}" rel="tag"> + <a href="{% url questions %}?tags={{tag|urlencode}}" + title="{% blocktrans %}see questions tagged '{{ tag }}'{% endblocktrans %}" rel="tag"> {{ tag }} </a> <span class="tag-number">× {{ tag.used_count|intcomma }}</span> diff --git a/forum/skins/default/templates/user.html b/forum/skins/default/templates/user.html index 5931f31c..8fd9e267 100644 --- a/forum/skins/default/templates/user.html +++ b/forum/skins/default/templates/user.html @@ -1,4 +1,4 @@ -{% extends "base_content.html" %} +{% extends "base.html" %} <!-- user.html --> {% load extra_tags %} {% load extra_filters %} diff --git a/forum/skins/default/templates/user_reputation.html b/forum/skins/default/templates/user_reputation.html index 954fb44d..f6a33d93 100644 --- a/forum/skins/default/templates/user_reputation.html +++ b/forum/skins/default/templates/user_reputation.html @@ -4,6 +4,7 @@ {% load extra_filters %} {% load humanize %} {% load i18n %} +{% load smart_if %} {% block userjs %} <script type='text/javascript' src='{% media "/media/js/excanvas.min.js" %}'></script> <script type='text/javascript' src='{% media "/media/js/jquery.flot.min.js" %}'></script> @@ -24,7 +25,11 @@ {% block usercontent %} <div class="karma-summary"> <div id="diagram" class="karma-diagram"></div> - <h3>{% trans "Change in karma per question or answer" %}</h3> + {% if view_user.id == user.id %} + <h3>{% trans "Your karma change log." %}</h3> + {% else %} + <h3>{% blocktrans with view_user.username as user_name %}{{user_name}}'s karma change log{% endblocktrans %}</h3> + {% endif %} <div class="karma-details"> {% for rep in reputation %} <p> diff --git a/forum/skins/default/templates/user_stats.html b/forum/skins/default/templates/user_stats.html index 1f462581..482b1228 100644 --- a/forum/skins/default/templates/user_stats.html +++ b/forum/skins/default/templates/user_stats.html @@ -98,7 +98,7 @@ {% for tag in user_tags%} <a rel="tag" title="{% blocktrans with tag.name as tag_name %}see other questions with {{view_user}}'s contributions tagged '{{ tag_name }}' {% endblocktrans %}" - href="{% url tag_questions tag|urlencode %}?user={{view_user.username}}">{{tag.name}}</a> + href="{% url questions %}?tags={{tag|urlencode}}&author={{view_user.id}}&start_over=true">{{tag.name}}</a> <span class="tag-number">× {{ tag.user_tag_usage_count|intcomma }}</span><br/> {% if forloop.counter|divisibleby:"10" %} </td> diff --git a/forum/skins/default/templates/users.html b/forum/skins/default/templates/users.html index 78715e05..f3ccd6e9 100644 --- a/forum/skins/default/templates/users.html +++ b/forum/skins/default/templates/users.html @@ -1,4 +1,4 @@ -{% extends "base_content.html" %} +{% extends "base.html" %} <!-- users.html --> {% load extra_tags %} {% load humanize %} diff --git a/forum/skins/default/templates/users_questions.html b/forum/skins/default/templates/users_questions.html index be6aaf7d..99a7f90c 100644 --- a/forum/skins/default/templates/users_questions.html +++ b/forum/skins/default/templates/users_questions.html @@ -31,7 +31,7 @@ {% convert2tagname_list question %} {% for tag in question.tagnames %} <!--todo - move trans below to blocktrans --> - <a href="{% url tag_questions tag|urlencode %}" title="{% trans "see questions tagged" %} '{{ tag }}' {% trans "using tags" %}" rel="tag">{{ tag }}</a> + <a href="{% url questions %}?tags={{tag|urlencode}}" title="{% blocktrans %}see questions tagged '{{ tag }}'{% endblocktrans %}" rel="tag">{{ tag }}</a> {% endfor %} </div> <div class="started"> diff --git a/sql_scripts/091111_upgrade_evgeny.sql b/forum/sql_scripts/091111_upgrade_evgeny.sql index cb76ec3c..cb76ec3c 100644 --- a/sql_scripts/091111_upgrade_evgeny.sql +++ b/forum/sql_scripts/091111_upgrade_evgeny.sql diff --git a/sql_scripts/091208_upgrade_evgeny.sql b/forum/sql_scripts/091208_upgrade_evgeny.sql index d9c4289a..d9c4289a 100644 --- a/sql_scripts/091208_upgrade_evgeny.sql +++ b/forum/sql_scripts/091208_upgrade_evgeny.sql diff --git a/sql_scripts/091208_upgrade_evgeny_1.sql b/forum/sql_scripts/091208_upgrade_evgeny_1.sql index b1b4107f..b1b4107f 100644 --- a/sql_scripts/091208_upgrade_evgeny_1.sql +++ b/forum/sql_scripts/091208_upgrade_evgeny_1.sql diff --git a/sql_scripts/100108_upgrade_ef.sql b/forum/sql_scripts/100108_upgrade_ef.sql index 1c9a5c1c..1c9a5c1c 100644 --- a/sql_scripts/100108_upgrade_ef.sql +++ b/forum/sql_scripts/100108_upgrade_ef.sql diff --git a/sql_scripts/badges.sql b/forum/sql_scripts/badges.sql index 5fd03d18..5fd03d18 100644 --- a/sql_scripts/badges.sql +++ b/forum/sql_scripts/badges.sql diff --git a/sql_scripts/cnprog.xml b/forum/sql_scripts/cnprog.xml index 95f9b362..95f9b362 100644 --- a/sql_scripts/cnprog.xml +++ b/forum/sql_scripts/cnprog.xml diff --git a/sql_scripts/cnprog_new_install.sql b/forum/sql_scripts/cnprog_new_install.sql index ac33a6ba..ac33a6ba 100644 --- a/sql_scripts/cnprog_new_install.sql +++ b/forum/sql_scripts/cnprog_new_install.sql diff --git a/sql_scripts/cnprog_new_install_2009_02_28.sql b/forum/sql_scripts/cnprog_new_install_2009_02_28.sql index 80b9fced..80b9fced 100644 --- a/sql_scripts/cnprog_new_install_2009_02_28.sql +++ b/forum/sql_scripts/cnprog_new_install_2009_02_28.sql diff --git a/sql_scripts/cnprog_new_install_2009_03_31.sql b/forum/sql_scripts/cnprog_new_install_2009_03_31.sql index c2c69f36..c2c69f36 100644 --- a/sql_scripts/cnprog_new_install_2009_03_31.sql +++ b/forum/sql_scripts/cnprog_new_install_2009_03_31.sql diff --git a/sql_scripts/cnprog_new_install_2009_04_07.sql b/forum/sql_scripts/cnprog_new_install_2009_04_07.sql index ff9016fa..ff9016fa 100644 --- a/sql_scripts/cnprog_new_install_2009_04_07.sql +++ b/forum/sql_scripts/cnprog_new_install_2009_04_07.sql diff --git a/sql_scripts/cnprog_new_install_2009_04_09.sql b/forum/sql_scripts/cnprog_new_install_2009_04_09.sql index f4424852..f4424852 100644 --- a/sql_scripts/cnprog_new_install_2009_04_09.sql +++ b/forum/sql_scripts/cnprog_new_install_2009_04_09.sql diff --git a/sql_scripts/drop-all-tables.sh b/forum/sql_scripts/drop-all-tables.sh index 1e55cb1f..1e55cb1f 100644 --- a/sql_scripts/drop-all-tables.sh +++ b/forum/sql_scripts/drop-all-tables.sh diff --git a/sql_scripts/drop-auth.sql b/forum/sql_scripts/drop-auth.sql index bc17dce3..bc17dce3 100644 --- a/sql_scripts/drop-auth.sql +++ b/forum/sql_scripts/drop-auth.sql diff --git a/sql_scripts/pg_fts_install.sql b/forum/sql_scripts/pg_fts_install.sql index d0655134..d0655134 100644 --- a/sql_scripts/pg_fts_install.sql +++ b/forum/sql_scripts/pg_fts_install.sql diff --git a/sql_scripts/update_2009_01_13_001.sql b/forum/sql_scripts/update_2009_01_13_001.sql index 165d1125..165d1125 100644 --- a/sql_scripts/update_2009_01_13_001.sql +++ b/forum/sql_scripts/update_2009_01_13_001.sql diff --git a/sql_scripts/update_2009_01_13_002.sql b/forum/sql_scripts/update_2009_01_13_002.sql index c223cb8c..c223cb8c 100644 --- a/sql_scripts/update_2009_01_13_002.sql +++ b/forum/sql_scripts/update_2009_01_13_002.sql diff --git a/sql_scripts/update_2009_01_18_001.sql b/forum/sql_scripts/update_2009_01_18_001.sql index 6f29fa32..6f29fa32 100644 --- a/sql_scripts/update_2009_01_18_001.sql +++ b/forum/sql_scripts/update_2009_01_18_001.sql diff --git a/sql_scripts/update_2009_01_24.sql b/forum/sql_scripts/update_2009_01_24.sql index 45b83935..45b83935 100644 --- a/sql_scripts/update_2009_01_24.sql +++ b/forum/sql_scripts/update_2009_01_24.sql diff --git a/sql_scripts/update_2009_01_25_001.sql b/forum/sql_scripts/update_2009_01_25_001.sql index 16c3487b..16c3487b 100644 --- a/sql_scripts/update_2009_01_25_001.sql +++ b/forum/sql_scripts/update_2009_01_25_001.sql diff --git a/sql_scripts/update_2009_02_26_001.sql b/forum/sql_scripts/update_2009_02_26_001.sql index a6af5931..a6af5931 100644 --- a/sql_scripts/update_2009_02_26_001.sql +++ b/forum/sql_scripts/update_2009_02_26_001.sql diff --git a/sql_scripts/update_2009_04_10_001.sql b/forum/sql_scripts/update_2009_04_10_001.sql index 8148632a..8148632a 100644 --- a/sql_scripts/update_2009_04_10_001.sql +++ b/forum/sql_scripts/update_2009_04_10_001.sql diff --git a/sql_scripts/update_2009_07_05_EF.sql b/forum/sql_scripts/update_2009_07_05_EF.sql index 43c7c2f0..43c7c2f0 100644 --- a/sql_scripts/update_2009_07_05_EF.sql +++ b/forum/sql_scripts/update_2009_07_05_EF.sql diff --git a/sql_scripts/update_2009_12_24_001.sql b/forum/sql_scripts/update_2009_12_24_001.sql index 3d082c2f..3d082c2f 100644 --- a/sql_scripts/update_2009_12_24_001.sql +++ b/forum/sql_scripts/update_2009_12_24_001.sql diff --git a/sql_scripts/update_2009_12_27_001.sql b/forum/sql_scripts/update_2009_12_27_001.sql index e2da7d4d..e2da7d4d 100644 --- a/sql_scripts/update_2009_12_27_001.sql +++ b/forum/sql_scripts/update_2009_12_27_001.sql diff --git a/sql_scripts/update_2009_12_27_002.sql b/forum/sql_scripts/update_2009_12_27_002.sql index a36470bf..a36470bf 100644 --- a/sql_scripts/update_2009_12_27_002.sql +++ b/forum/sql_scripts/update_2009_12_27_002.sql diff --git a/sql_scripts/update_2010_01_23.sql b/forum/sql_scripts/update_2010_01_23.sql index 621207be..621207be 100755 --- a/sql_scripts/update_2010_01_23.sql +++ b/forum/sql_scripts/update_2010_01_23.sql diff --git a/sql_scripts/update_2010_02_22.sql b/forum/sql_scripts/update_2010_02_22.sql index 2778885a..2778885a 100644 --- a/sql_scripts/update_2010_02_22.sql +++ b/forum/sql_scripts/update_2010_02_22.sql diff --git a/forum/templatetags/extra_tags.py b/forum/templatetags/extra_tags.py index 382d19f0..83aeb4c7 100755 --- a/forum/templatetags/extra_tags.py +++ b/forum/templatetags/extra_tags.py @@ -304,8 +304,12 @@ class ItemSeparatorNode(template.Node): return self.content class JoinItemListNode(template.Node): - def __init__(self,separator=ItemSeparatorNode("''"), items=()): + def __init__(self,separator=ItemSeparatorNode("''"), last_separator=None, items=()): self.separator = separator + if last_separator: + self.last_separator = last_separator + else: + self.last_separator = separator self.items = items def render(self,context): out = [] @@ -314,16 +318,34 @@ class JoinItemListNode(template.Node): bit = item.render(context) if not empty_re.search(bit): out.append(bit) - return self.separator.render(context).join(out) + if len(out) == 1: + return out[0] + if len(out) > 1: + last = out.pop() + all_but_last = self.separator.render(context).join(out) + return self.last_separator.render(context).join((all_but_last,last)) + else: + assert(len(out)==0) + return '' @register.tag(name="joinitems") def joinitems(parser,token): try: - tagname,junk,sep_token = token.split_contents() - except ValueError: - raise template.TemplateSyntaxError("joinitems tag requires 'using \"separator html\"' parameters") + tagname, junk, sep_token = token.split_contents() + last_sep_token = None + except: + try: + tagname, junk, sep_token, last_sep_token = token.split_contents() + except: + raise template.TemplateSyntaxError('incorrect usage of joinitems tag first param ' + 'must be \'using\' second - separator and ' + 'optional third - last item separator') if junk == 'using': sep_node = ItemSeparatorNode(sep_token) + if last_sep_token: + last_sep_node = ItemSeparatorNode(last_sep_token) + else: + last_sep_node = None else: raise template.TemplateSyntaxError("joinitems tag requires 'using \"separator html\"' parameters") nodelist = [] @@ -333,7 +355,7 @@ def joinitems(parser,token): if next.contents == 'endjoinitems': break - return JoinItemListNode(separator=sep_node,items=nodelist) + return JoinItemListNode(separator=sep_node,last_separator=last_sep_node,items=nodelist) class BlockMediaUrlNode(template.Node): def __init__(self,nodelist): @@ -436,3 +458,46 @@ def question_counter_widget(question): #returns a dictionary with keys like 'votes_bg', etc return locals() +class IsManyNode(template.Node): + def __init__(self, test_items, true_nodelist, false_nodelist): + self.true_nodelist = true_nodelist + self.false_nodelist = false_nodelist + self.test_items = test_items + def render(self, context): + maybe = False + for item in self.test_items: + is_good = item.resolve(context) + if maybe == True and is_good: + return self.true_nodelist.render(context) + if is_good: + maybe = True + return self.false_nodelist.render(context) + +@register.tag(name='ifmany') +def ifmany(parser,token): + """usage {% ifmany item1 item2 item3 ... itemN %} stuff {% endifmany %} + returns content included into the tag if more than one + item evaluates to Tru'ish value - that's the idea + {% else %} is not supported yet + """ + + bits = list(token.split_contents()) + start_tag = bits.pop(0) + + test_items = [] + for bit in bits: + item = parser.compile_filter(bit) + test_items.append(item) + + end_tag = 'end' + start_tag + else_tag = 'else' + true_nodelist = parser.parse((end_tag,else_tag,)) + token = parser.next_token() + if token.contents == else_tag: + false_nodelist = parser.parse((end_tag,)) + token = parser.next_token() + else: + false_nodelist = template.NodeList() + + + return IsManyNode(test_items, true_nodelist, false_nodelist) diff --git a/forum/utils/decorators.py b/forum/utils/decorators.py index e4e7acb3..440e8312 100755 --- a/forum/utils/decorators.py +++ b/forum/utils/decorators.py @@ -22,4 +22,3 @@ def ajax_method(view_func): json = simplejson.dumps(retval) return HttpResponse(json,mimetype='application/json') return wrap - diff --git a/forum/views/readers.py b/forum/views/readers.py index 3f0bef0f..89a9550b 100644 --- a/forum/views/readers.py +++ b/forum/views/readers.py @@ -13,7 +13,6 @@ from django.db.models import Q from django.utils.translation import ugettext as _ from django.template.defaultfilters import slugify from django.core.urlresolvers import reverse -from django.utils.datastructures import SortedDict from django.views.decorators.cache import cache_page from forum.utils.html import sanitize_html @@ -24,8 +23,10 @@ from forum.forms import * from forum.models import * from forum.auth import * from forum.const import * +from forum import const from forum import auth from forum.utils.forms import get_next_url +from forum.search.state_manager import SearchState # used in index page #refactor - move these numbers somewhere? @@ -35,7 +36,6 @@ INDEX_TAGS_SIZE = 25 # used in tags list DEFAULT_PAGE_SIZE = 60 # used in questions -QUESTIONS_PAGE_SIZE = 30 # used in answers ANSWERS_PAGE_SIZE = 10 @@ -54,24 +54,6 @@ def _get_tags_cache_json():#service routine used by views requiring tag list in tags = simplejson.dumps(tags_list) return tags -def _get_and_remember_questions_sort_method(request, view_dic, default):#service routine used by q listing views and question view - """manages persistence of post sort order - it is assumed that when user wants newest question - - then he/she wants newest answers as well, etc. - how far should this assumption actually go - may be a good question - """ - if default not in view_dic: - raise Exception('default value must be in view_dic') - - q_sort_method = request.REQUEST.get('sort', None) - if q_sort_method == None: - q_sort_method = request.session.get('questions_sort_method', default) - - if q_sort_method not in view_dic: - q_sort_method = default - request.session['questions_sort_method'] = q_sort_method - return q_sort_method, view_dic[q_sort_method] - #refactor? - we have these #views that generate a listing of questions in one way or another: #index, unanswered, questions, search, tag @@ -81,280 +63,122 @@ def _get_and_remember_questions_sort_method(request, view_dic, default):#service def index(request):#generates front page - shows listing of questions sorted in various ways """index view mapped to the root url of the Q&A site """ - view_dic = { - "latest":"-last_activity_at", - "hottest":"-answer_count", - "mostvoted":"-score", - } - view_id, orderby = _get_and_remember_questions_sort_method(request, view_dic, 'latest') - - pagesize = request.session.get("pagesize",QUESTIONS_PAGE_SIZE) - try: - page = int(request.GET.get('page', '1')) - except ValueError: - page = 1 - - qs = Question.objects.exclude(deleted=True).order_by(orderby) - - objects_list = Paginator(qs, pagesize) - questions = objects_list.page(page) - - # RISK - inner join queries - #questions = questions.select_related() - tags = Tag.objects.get_valid_tags(INDEX_TAGS_SIZE) - - awards = Award.objects.get_recent_awards() - - (interesting_tag_names, ignored_tag_names) = (None, None) - if request.user.is_authenticated(): - pt = MarkedTag.objects.filter(user=request.user) - interesting_tag_names = pt.filter(reason='good').values_list('tag__name', flat=True) - ignored_tag_names = pt.filter(reason='bad').values_list('tag__name', flat=True) - - tags_autocomplete = _get_tags_cache_json() - - return render_to_response('index.html', { - 'interesting_tag_names': interesting_tag_names, - 'tags_autocomplete': tags_autocomplete, - 'ignored_tag_names': ignored_tag_names, - "questions" : questions, - "tab_id" : view_id, - "tags" : tags, - "awards" : awards[:INDEX_AWARD_SIZE], - "context" : { - 'is_paginated' : True, - 'pages': objects_list.num_pages, - 'page': page, - 'has_previous': questions.has_previous(), - 'has_next': questions.has_next(), - 'previous': questions.previous_page_number(), - 'next': questions.next_page_number(), - 'base_url' : request.path + '?sort=%s&' % view_id, - 'pagesize' : pagesize - }}, context_instance=RequestContext(request)) + return HttpResponseRedirect(reverse('questions')) +#todo: eliminate this from urls def unanswered(request):#generates listing of unanswered questions return questions(request, unanswered=True) -def questions(request, tagname=None, unanswered=False):#a view generating listing of questions, used by 'unanswered' too +def questions(request):#a view generating listing of questions, used by 'unanswered' too """ List of Questions, Tagged questions, and Unanswered questions. """ - # template file - # "questions.html" or maybe index.html in the future - template_file = "questions.html" - # Set flag to False by default. If it is equal to True, then need to be saved. - pagesize_changed = False - # get pagesize from session, if failed then get default value - pagesize = request.session.get("pagesize",QUESTIONS_PAGE_SIZE) - try: - page = int(request.GET.get('page', '1')) - except ValueError: - page = 1 - view_dic = {"latest":"-added_at", "active":"-last_activity_at", "hottest":"-answer_count", "mostvoted":"-score" } - view_id, orderby = _get_and_remember_questions_sort_method(request,view_dic,'latest') - - # check if request is from tagged questions - qs = Question.objects.exclude(deleted=True) + #don't allow to post to this view + if request.method == 'POST': + raise Http404 - if tagname is not None: - qs = qs.filter(tags__name = unquote(tagname)) + #todo: redo SearchState to accept input from + #view_log, session and request parameters + search_state = request.session.get('search_state', SearchState()) - if unanswered: - qs = qs.exclude(answer_accepted=True) + view_log = request.session['view_log'] - author_name = None - #user contributed questions & answers - if 'user' in request.GET: - try: - author_name = request.GET['user'] - u = User.objects.get(username=author_name) - qs = qs.filter(Q(author=u) | Q(answers__author=u)) - except User.DoesNotExist: - author_name = None + if view_log.get_previous(1) != 'questions': + if view_log.get_previous(2) != 'questions': + #print 'user stepped too far, resetting search state' + search_state.reset() if request.user.is_authenticated(): - uid_str = str(request.user.id) - qs = qs.extra( - select = SortedDict([ - ( - 'interesting_score', - 'SELECT COUNT(1) FROM forum_markedtag, question_tags ' - + 'WHERE forum_markedtag.user_id = %s ' - + 'AND forum_markedtag.tag_id = question_tags.tag_id ' - + 'AND forum_markedtag.reason = \'good\' ' - + 'AND question_tags.question_id = question.id' - ), - ]), - select_params = (uid_str,), - ) - if request.user.hide_ignored_questions: - ignored_tags = Tag.objects.filter(user_selections__reason='bad', - user_selections__user = request.user) - qs = qs.exclude(tags__in=ignored_tags) - else: - qs = qs.extra( - select = SortedDict([ - ( - 'ignored_score', - 'SELECT COUNT(1) FROM forum_markedtag, question_tags ' - + 'WHERE forum_markedtag.user_id = %s ' - + 'AND forum_markedtag.tag_id = question_tags.tag_id ' - + 'AND forum_markedtag.reason = \'bad\' ' - + 'AND question_tags.question_id = question.id' - ) - ]), - select_params = (uid_str, ) - ) - - qs = qs.select_related(depth=1).order_by(orderby) - - objects_list = Paginator(qs, pagesize) - questions = objects_list.page(page) - - # Get related tags from this page objects - if questions.object_list.count() > 0: - related_tags = Tag.objects.get_tags_by_questions(questions.object_list) - else: - related_tags = None - tags_autocomplete = _get_tags_cache_json() + search_state.set_logged_in() + + form = AdvancedSearchForm(request.GET) + #todo: form is used only for validation... + if form.is_valid(): + search_state.update_from_user_input( + form.cleaned_data, + request.GET, + ) + #todo: better put these in separately then analyze + #what neesd to be done, otherwise there are two routines + #that take request.GET I don't like this use of parameters + #another weakness is that order of routine calls matters here + search_state.relax_stickiness( request.GET, view_log ) + + request.session['search_state'] = search_state + request.session.modified = True + + #force reset for debugging + #search_state.reset() + #request.session.modified = True + + #have this call implemented for sphinx, mysql and pgsql + (qs, meta_data) = Question.objects.run_advanced_search( + request_user = request.user, + scope_selector = search_state.scope,#unanswered/all/favorite (for logged in) + search_query = search_state.query, + tag_selector = search_state.tags, + author_selector = search_state.author, + sort_method = search_state.sort + ) + + objects_list = Paginator(qs, search_state.page_size) + questions = objects_list.page(search_state.page) + + #todo maybe do this search on query the set instead + related_tags = Tag.objects.get_tags_by_questions(questions.object_list) - # get the list of interesting and ignored tags - (interesting_tag_names, ignored_tag_names) = (None, None) - if request.user.is_authenticated(): - pt = MarkedTag.objects.filter(user=request.user) - interesting_tag_names = pt.filter(reason='good').values_list('tag__name', flat=True) - ignored_tag_names = pt.filter(reason='bad').values_list('tag__name', flat=True) + tags_autocomplete = _get_tags_cache_json() - return render_to_response(template_file, { - "questions" : questions, - "author_name" : author_name, - "tab_id" : view_id, - "questions_count" : objects_list.count, - "tags" : related_tags, - "tags_autocomplete" : tags_autocomplete, - "searchtag" : tagname, - "is_unanswered" : unanswered, - "interesting_tag_names": interesting_tag_names, - 'ignored_tag_names': ignored_tag_names, - "context" : { + #todo!!!! + #contributors = #User.objects.get_related_to_questions + + #todo: organize variables by type + return render_to_response('questions.html', { + 'questions' : questions, + 'author_name' : meta_data.get('author_name',None), + 'tab_id' : search_state.sort, + 'questions_count' : objects_list.count, + 'tags' : related_tags, + 'query': search_state.query, + 'search_tags' : search_state.tags, + 'tags_autocomplete' : tags_autocomplete, + 'is_unanswered' : False,#remove this from template + 'interesting_tag_names': meta_data.get('interesting_tag_names',None), + 'ignored_tag_names': meta_data.get('ignored_tag_names',None), + 'sort': search_state.sort, + 'scope': search_state.scope, + 'context' : { 'is_paginated' : True, 'pages': objects_list.num_pages, - 'page': page, + 'page': search_state.page, 'has_previous': questions.has_previous(), 'has_next': questions.has_next(), 'previous': questions.previous_page_number(), 'next': questions.next_page_number(), - 'base_url' : request.path + '?sort=%s&' % view_id, - 'pagesize' : pagesize + 'base_url' : request.path + '?sort=%s&' % search_state.sort,#todo in T sort=>sort_method + 'pagesize' : search_state.page_size,#todo in T pagesize -> page_size }}, context_instance=RequestContext(request)) def search(request): #generates listing of questions matching a search query - including tags and just words - """generates listing of questions matching a search query - supports full text search in mysql db using sphinx and internally in postgresql - falls back on simple partial string matching approach if - full text search function is not available + """redirects to people and tag search pages + todo: eliminate this altogether and instead make + search "tab" sensitive automatically - the radio-buttons + are useless under the search bar """ if request.method == "GET": - keywords = request.GET.get("q") - search_type = request.GET.get("t") + search_type = request.GET.get('t') + query = request.GET.get('query') try: page = int(request.GET.get('page', '1')) except ValueError: page = 1 - if keywords is None: - return HttpResponseRedirect(reverse(index)) if search_type == 'tag': - return HttpResponseRedirect(reverse('tags') + '?q=%s&page=%s' % (keywords.strip(), page)) - elif search_type == "user": - return HttpResponseRedirect(reverse('users') + '?q=%s&page=%s' % (keywords.strip(), page)) - elif search_type == "question": - - template_file = "questions.html" - # Set flag to False by default. If it is equal to True, then need to be saved. - pagesize_changed = False - # get pagesize from session, if failed then get default value - user_page_size = request.session.get("pagesize", QUESTIONS_PAGE_SIZE) - # set pagesize equal to logon user specified value in database - if request.user.is_authenticated() and request.user.questions_per_page > 0: - user_page_size = request.user.questions_per_page - - try: - page = int(request.GET.get('page', '1')) - # get new pagesize from UI selection - pagesize = int(request.GET.get('pagesize', user_page_size)) - if pagesize <> user_page_size: - pagesize_changed = True - - except ValueError: - page = 1 - pagesize = user_page_size - - # save this pagesize to user database - if pagesize_changed: - request.session["pagesize"] = pagesize - if request.user.is_authenticated(): - user = request.user - user.questions_per_page = pagesize - user.save() - - view_id = request.GET.get('sort', None) - view_dic = {"latest":"-added_at", "active":"-last_activity_at", "hottest":"-answer_count", "mostvoted":"-score" } - try: - orderby = view_dic[view_id] - except KeyError: - view_id = "latest" - orderby = "-added_at" - - def question_search(keywords, orderby): - objects = Question.objects.filter(deleted=False).extra(where=['title like %s'], params=['%' + keywords + '%']).order_by(orderby) - # RISK - inner join queries - return objects.select_related(); - - from forum.modules import get_handler - - question_search = get_handler('question_search', question_search) - - objects = question_search(keywords, orderby) - - objects_list = Paginator(objects, pagesize) - questions = objects_list.page(page) - - # Get related tags from this page objects - related_tags = [] - for question in questions.object_list: - tags = list(question.tags.all()) - for tag in tags: - if tag not in related_tags: - related_tags.append(tag) - - #if is_search is true in the context, prepend this string to soting tabs urls - search_uri = "?q=%s&page=%d&t=question" % ("+".join(keywords.split()), page) - - return render_to_response(template_file, { - "questions" : questions, - "tab_id" : view_id, - "questions_count" : objects_list.count, - "tags" : related_tags, - "searchtag" : None, - "searchtitle" : keywords, - "keywords" : keywords, - "is_unanswered" : False, - "is_search": True, - "search_uri": search_uri, - "context" : { - 'is_paginated' : True, - 'pages': objects_list.num_pages, - 'page': page, - 'has_previous': questions.has_previous(), - 'has_next': questions.has_next(), - 'previous': questions.previous_page_number(), - 'next': questions.next_page_number(), - 'base_url' : request.path + '?t=question&q=%s&sort=%s&' % (keywords, view_id), - 'pagesize' : pagesize - }}, context_instance=RequestContext(request)) - + return HttpResponseRedirect(reverse('tags') + '?q=%s&page=%s' % (query.strip(), page)) + elif search_type == 'user': + return HttpResponseRedirect(reverse('users') + '?q=%s&page=%s' % (query.strip(), page)) + else: + raise Http404 else: raise Http404 @@ -386,6 +210,7 @@ def tags(request):#view showing a listing of available tags - plain list tags = objects_list.page(objects_list.num_pages) return render_to_response('tags.html', { + "active_tab": "tags", "tags" : tags, "stag" : stag, "tab_id" : sortby, diff --git a/forum/views/users.py b/forum/views/users.py index 705bbbb0..113c46e6 100755 --- a/forum/views/users.py +++ b/forum/views/users.py @@ -17,6 +17,7 @@ from forum import auth import calendar from django.contrib.contenttypes.models import ContentType from forum.models import user_updated +from forum.const import USERS_PAGE_SIZE from django.conf import settings question_type = ContentType.objects.get_for_model(Question) @@ -32,8 +33,6 @@ question_revision_type_id = question_revision_type.id answer_revision_type_id = answer_revision_type.id repute_type_id = repute_type.id -USERS_PAGE_SIZE = 35# refactor - move to some constants file - def users(request): is_paginated = True sortby = request.GET.get('sort', 'reputation') @@ -65,11 +64,12 @@ def users(request): users = objects_list.page(objects_list.num_pages) return render_to_response('users.html', { - "users" : users, - "suser" : suser, - "keywords" : suser, - "tab_id" : sortby, - "context" : { + 'active_tab': 'users', + 'users' : users, + 'suser' : suser, + 'keywords' : suser, + 'tab_id' : sortby, + 'context' : { 'is_paginated' : is_paginated, 'pages': objects_list.num_pages, 'page': page, @@ -124,6 +124,7 @@ def edit_user(request, id): if settings.EDITABLE_SCREEN_NAME: user.username = sanitize_html(form.cleaned_data['username']) + user.real_name = sanitize_html(form.cleaned_data['realname']) user.website = sanitize_html(form.cleaned_data['website']) user.location = sanitize_html(form.cleaned_data['city']) diff --git a/forum/views/writers.py b/forum/views/writers.py index b9b1aad5..57c8e043 100755 --- a/forum/views/writers.py +++ b/forum/views/writers.py @@ -132,9 +132,18 @@ def ask(request):#view used to ask a new question return HttpResponseRedirect(reverse('user_signin_new_question')) else: form = AskForm() + if 'title' in request.GET: + raw_title = request.GET['title'] + form.initial['title'] = strip_tags(strip_entities(raw_title)) + else: + search_state = request.session.get('search_state',None) + if search_state: + query = search_state.query + form.initial['title'] = query tags = _get_tags_cache_json() return render_to_response('ask.html', { + 'active_tab': 'ask', 'form' : form, 'tags' : tags, 'email_validation_faq_url':reverse('faq') + '#validate', @@ -318,7 +327,6 @@ def __generate_comments_json(obj, type, user):#non-view generates json data for data = simplejson.dumps(json_comments) return HttpResponse(data, mimetype="application/json") - def question_comments(request, id):#ajax handler for loading comments to question question = get_object_or_404(Question, id=id) user = request.user diff --git a/forum_modules/pgfulltext/DISABLED b/forum_modules/pgfulltext/DISABLED index e69de29b..e69de29b 100755..100644 --- a/forum_modules/pgfulltext/DISABLED +++ b/forum_modules/pgfulltext/DISABLED diff --git a/forum_modules/pgfulltext/__init__.py b/forum_modules/pgfulltext/__init__.py index 8215e1a9..8215e1a9 100755..100644 --- a/forum_modules/pgfulltext/__init__.py +++ b/forum_modules/pgfulltext/__init__.py diff --git a/forum_modules/pgfulltext/handlers.py b/forum_modules/pgfulltext/handlers.py index f4a7a3b2..f4a7a3b2 100755..100644 --- a/forum_modules/pgfulltext/handlers.py +++ b/forum_modules/pgfulltext/handlers.py diff --git a/forum_modules/pgfulltext/management.py b/forum_modules/pgfulltext/management.py index 15ba3bd7..15ba3bd7 100755..100644 --- a/forum_modules/pgfulltext/management.py +++ b/forum_modules/pgfulltext/management.py diff --git a/forum_modules/pgfulltext/pg_fts_install.sql b/forum_modules/pgfulltext/pg_fts_install.sql index 72eca516..72eca516 100755..100644 --- a/forum_modules/pgfulltext/pg_fts_install.sql +++ b/forum_modules/pgfulltext/pg_fts_install.sql diff --git a/forum_modules/sphinxfulltext/DISABLED b/forum_modules/sphinxfulltext/DISABLED index e69de29b..e69de29b 100755..100644 --- a/forum_modules/sphinxfulltext/DISABLED +++ b/forum_modules/sphinxfulltext/DISABLED diff --git a/forum_modules/sphinxfulltext/__init__.py b/forum_modules/sphinxfulltext/__init__.py index e69de29b..e69de29b 100755..100644 --- a/forum_modules/sphinxfulltext/__init__.py +++ b/forum_modules/sphinxfulltext/__init__.py diff --git a/forum_modules/sphinxfulltext/dependencies.py b/forum_modules/sphinxfulltext/dependencies.py index 046ebfc5..046ebfc5 100755..100644 --- a/forum_modules/sphinxfulltext/dependencies.py +++ b/forum_modules/sphinxfulltext/dependencies.py diff --git a/forum_modules/sphinxfulltext/handlers.py b/forum_modules/sphinxfulltext/handlers.py index 226acf72..226acf72 100755..100644 --- a/forum_modules/sphinxfulltext/handlers.py +++ b/forum_modules/sphinxfulltext/handlers.py diff --git a/forum_modules/sphinxfulltext/models.py b/forum_modules/sphinxfulltext/models.py index a188728d..a188728d 100755..100644 --- a/forum_modules/sphinxfulltext/models.py +++ b/forum_modules/sphinxfulltext/models.py diff --git a/forum_modules/sphinxfulltext/settings.py b/forum_modules/sphinxfulltext/settings.py index 564404c6..564404c6 100755..100644 --- a/forum_modules/sphinxfulltext/settings.py +++ b/forum_modules/sphinxfulltext/settings.py diff --git a/locale/en/LC_MESSAGES/django.mo b/locale/en/LC_MESSAGES/django.mo Binary files differindex 65af2080..cac204e1 100644 --- a/locale/en/LC_MESSAGES/django.mo +++ b/locale/en/LC_MESSAGES/django.mo diff --git a/locale/en/LC_MESSAGES/django.po b/locale/en/LC_MESSAGES/django.po index 23e1d410..e773b46f 100644 --- a/locale/en/LC_MESSAGES/django.po +++ b/locale/en/LC_MESSAGES/django.po @@ -1690,7 +1690,7 @@ msgstr "" #: forum/skins/default/templates/header.html:29 #: forum/skins/default/templates/header.html:57 msgid "users" -msgstr "" +msgstr "people" #: forum/skins/default/templates/header.html:31 msgid "books" diff --git a/locale/ru/LC_MESSAGES/django.mo b/locale/ru/LC_MESSAGES/django.mo Binary files differnew file mode 100644 index 00000000..c2241644 --- /dev/null +++ b/locale/ru/LC_MESSAGES/django.mo diff --git a/locale/ru/LC_MESSAGES/django.po b/locale/ru/LC_MESSAGES/django.po new file mode 100644 index 00000000..8fc6c6c0 --- /dev/null +++ b/locale/ru/LC_MESSAGES/django.po @@ -0,0 +1,3600 @@ +# Russian translation of messages for Askbot +# Copyright (C) 2009 Gang Chen +# This file is distributed under the same license as the Askbot package. +# FIRST AUTHOR <evgeny.fadeev@gmail.com>, 2010. +# +#, fuzzy +msgid "" +msgstr "" +"Project-Id-Version: PACKAGE VERSION\n" +"Report-Msgid-Bugs-To: \n" +"POT-Creation-Date: 2010-04-22 03:56-0400\n" +"PO-Revision-Date: YEAR-MO-DA HO:MI+ZONE\n" +"Last-Translator: FULL NAME <EMAIL@ADDRESS>\n" +"Language-Team: LANGUAGE <LL@li.org>\n" +"MIME-Version: 1.0\n" +"Content-Type: text/plain; charset=UTF-8\n" +"Content-Transfer-Encoding: 8bit\n" +"Plural-Forms: nplurals=3; plural=n%10==1 && n%100!=11 ? 0 : n%10>=2 && n%" +"10<=4 && (n%100<10 || n%100>=20) ? 1 : 2\n" + +#: django_authopenid/forms.py:71 django_authopenid/views.py:132 +msgid "i-names are not supported" +msgstr "" + +#: django_authopenid/forms.py:134 +msgid "Account with this name already exists on the forum" +msgstr "" + +#: django_authopenid/forms.py:135 +msgid "can't have two logins to the same account yet, sorry." +msgstr "" + +#: django_authopenid/forms.py:157 +msgid "Please enter valid username and password (both are case-sensitive)." +msgstr "" + +#: django_authopenid/forms.py:160 django_authopenid/forms.py:210 +msgid "This account is inactive." +msgstr "" + +#: django_authopenid/forms.py:162 +msgid "Login failed." +msgstr "" + +#: django_authopenid/forms.py:164 +msgid "Please enter username and password" +msgstr "" + +#: django_authopenid/forms.py:166 +msgid "Please enter your password" +msgstr "" + +#: django_authopenid/forms.py:168 +msgid "Please enter user name" +msgstr "" + +#: django_authopenid/forms.py:206 +msgid "" +"Please enter a valid username and password. Note that " +"both fields are case-sensitive." +msgstr "" + +#: django_authopenid/forms.py:229 forum/authentication/forms.py:60 +msgid "Current password" +msgstr "" + +#: django_authopenid/forms.py:240 forum/authentication/forms.py:71 +msgid "" +"Old password is incorrect. Please enter the correct " +"password." +msgstr "" + +#: django_authopenid/forms.py:305 +msgid "Your user name (<i>required</i>)" +msgstr "" + +#: django_authopenid/forms.py:320 +msgid "Incorrect username." +msgstr "" + +#: django_authopenid/urls.py:23 django_authopenid/urls.py:24 +#: django_authopenid/urls.py:25 django_authopenid/urls.py:27 +#: fbconnect/urls.py:12 fbconnect/urls.py:13 fbconnect/urls.py:14 +msgid "signin/" +msgstr "" + +#: django_authopenid/urls.py:24 fbconnect/urls.py:13 fbconnect/urls.py:17 +msgid "newquestion/" +msgstr "" + +#: django_authopenid/urls.py:25 fbconnect/urls.py:14 fbconnect/urls.py:18 +msgid "newanswer/" +msgstr "" + +#: django_authopenid/urls.py:26 +msgid "signout/" +msgstr "" + +#: django_authopenid/urls.py:27 +msgid "complete/" +msgstr "" + +#: django_authopenid/urls.py:29 fbconnect/urls.py:16 fbconnect/urls.py:17 +#: fbconnect/urls.py:18 +msgid "register/" +msgstr "" + +#: django_authopenid/urls.py:30 +msgid "signup/" +msgstr "" + +#: django_authopenid/urls.py:32 +msgid "sendpw/" +msgstr "" + +#: django_authopenid/urls.py:33 django_authopenid/urls.py:37 +msgid "password/" +msgstr "" + +#: django_authopenid/urls.py:33 +msgid "confirm/" +msgstr "" + +#: django_authopenid/urls.py:36 +msgid "account_settings" +msgstr "" + +#: django_authopenid/urls.py:38 django_authopenid/urls.py:39 +#: django_authopenid/urls.py:40 django_authopenid/urls.py:41 +msgid "email/" +msgstr "" + +#: django_authopenid/urls.py:38 +msgid "validate/" +msgstr "" + +#: django_authopenid/urls.py:39 +msgid "change/" +msgstr "" + +#: django_authopenid/urls.py:40 +msgid "sendkey/" +msgstr "" + +#: django_authopenid/urls.py:41 +msgid "verify/" +msgstr "" + +#: django_authopenid/urls.py:42 +msgid "openid/" +msgstr "" + +#: django_authopenid/urls.py:43 forum/urls.py:52 forum/urls.py:56 +msgid "delete/" +msgstr "" + +#: django_authopenid/urls.py:51 +msgid "external-login/forgot-password/" +msgstr "" + +#: django_authopenid/urls.py:54 +msgid "external-login/signup/" +msgstr "" + +#: django_authopenid/views.py:139 +#, python-format +msgid "OpenID %(openid_url)s is invalid" +msgstr "" + +#: django_authopenid/views.py:614 +msgid "Welcome email subject line" +msgstr "" + +#: django_authopenid/views.py:720 +msgid "Password changed." +msgstr "" + +#: django_authopenid/views.py:732 django_authopenid/views.py:738 +#, python-format +msgid "your email needs to be validated see %(details_url)s" +msgstr "" + +#: django_authopenid/views.py:759 +msgid "Email verification subject line" +msgstr "" + +#: django_authopenid/views.py:850 +msgid "your email was not changed" +msgstr "" + +#: django_authopenid/views.py:898 django_authopenid/views.py:1056 +#, python-format +msgid "No OpenID %s found associated in our database" +msgstr "" + +#: django_authopenid/views.py:902 django_authopenid/views.py:1063 +#, python-format +msgid "The OpenID %s isn't associated to current user logged in" +msgstr "" + +#: django_authopenid/views.py:910 +msgid "Email Changed." +msgstr "" + +#: django_authopenid/views.py:988 +msgid "This OpenID is already associated with another account." +msgstr "" + +#: django_authopenid/views.py:993 +#, python-format +msgid "OpenID %s is now associated with your account." +msgstr "" + +#: django_authopenid/views.py:1066 +msgid "Account deleted." +msgstr "" + +#: django_authopenid/views.py:1118 +msgid "Request for new password" +msgstr "" + +#: django_authopenid/views.py:1132 +msgid "A new password and the activation link were sent to your email address." +msgstr "" + +#: django_authopenid/views.py:1164 +#, python-format +msgid "" +"Could not change password. Confirmation key '%s' is not " +"registered." +msgstr "" + +#: django_authopenid/views.py:1174 +msgid "" +"Can not change password. User don't exist anymore in our " +"database." +msgstr "" + +#: django_authopenid/views.py:1184 +#, python-format +msgid "Password changed for %s. You may now sign in." +msgstr "" + +#: forum/auth.py:505 +msgid "Your question and all of it's answers have been deleted" +msgstr "" + +#: forum/auth.py:507 +msgid "Your question has been deleted" +msgstr "" + +#: forum/auth.py:510 +msgid "The question and all of it's answers have been deleted" +msgstr "" + +#: forum/auth.py:512 +msgid "The question has been deleted" +msgstr "" + +#: forum/const.py:8 +msgid "duplicate question" +msgstr "" + +#: forum/const.py:9 +msgid "question is off-topic or not relevant" +msgstr "" + +#: forum/const.py:10 +msgid "too subjective and argumentative" +msgstr "" + +#: forum/const.py:11 +msgid "not a real question" +msgstr "" + +#: forum/const.py:12 +msgid "the question is answered, right answer was accepted" +msgstr "" + +#: forum/const.py:13 +msgid "question is not relevant or outdated" +msgstr "" + +#: forum/const.py:14 +msgid "question contains offensive or malicious remarks" +msgstr "" + +#: forum/const.py:15 +msgid "spam or advertising" +msgstr "" + +#: forum/const.py:16 +msgid "too localized" +msgstr "" + +#: forum/const.py:37 forum/skins/default/templates/index.html:28 +#: forum/skins/default/templates/index_.html:27 +#: forum/skins/default/templates/questions.html:70 +#: forum/skins/default/templates/questions.html:75 +msgid "newest" +msgstr "" + +#: forum/const.py:38 forum/skins/default/templates/questions.html:64 +#: forum/skins/default/templates/users.html:28 +msgid "oldest" +msgstr "" + +#: forum/const.py:39 forum/skins/default/templates/questions.html:89 +#: forum/skins/default/templates/questions.html:94 +msgid "active" +msgstr "" + +#: forum/const.py:40 forum/skins/default/templates/questions.html:83 +msgid "inactive" +msgstr "" + +#: forum/const.py:41 forum/skins/default/templates/index.html:29 +#: forum/skins/default/templates/index_.html:28 +msgid "hottest" +msgstr "" + +#: forum/const.py:42 +msgid "coldest" +msgstr "" + +#: forum/const.py:43 forum/skins/default/templates/index.html:30 +#: forum/skins/default/templates/index_.html:29 +msgid "most voted" +msgstr "" + +#: forum/const.py:44 +msgid "least voted" +msgstr "" + +#: forum/const.py:45 +msgid "relevance" +msgstr "" + +#: forum/const.py:52 forum/skins/default/templates/questions.html:52 +msgid "all" +msgstr "" + +#: forum/const.py:53 forum/skins/default/templates/questions.html:53 +msgid "unanswered" +msgstr "" + +#: forum/const.py:54 forum/skins/default/templates/questions.html:55 +msgid "favorite" +msgstr "" + +#: forum/const.py:97 +msgid "question" +msgstr "" + +#: forum/const.py:98 forum/skins/default/templates/book.html:110 +msgid "answer" +msgstr "" + +#: forum/const.py:99 +msgid "commented question" +msgstr "" + +#: forum/const.py:100 +msgid "commented answer" +msgstr "" + +#: forum/const.py:101 +msgid "edited question" +msgstr "" + +#: forum/const.py:102 +msgid "edited answer" +msgstr "" + +#: forum/const.py:103 +msgid "received award" +msgstr "" + +#: forum/const.py:104 +msgid "marked best answer" +msgstr "" + +#: forum/const.py:105 +msgid "upvoted" +msgstr "" + +#: forum/const.py:106 +msgid "downvoted" +msgstr "" + +#: forum/const.py:107 +msgid "canceled vote" +msgstr "" + +#: forum/const.py:108 +msgid "deleted question" +msgstr "" + +#: forum/const.py:109 +msgid "deleted answer" +msgstr "" + +#: forum/const.py:110 +msgid "marked offensive" +msgstr "" + +#: forum/const.py:111 +msgid "updated tags" +msgstr "" + +#: forum/const.py:112 +msgid "selected favorite" +msgstr "" + +#: forum/const.py:113 +msgid "completed user profile" +msgstr "" + +#: forum/const.py:114 +msgid "email update sent to user" +msgstr "" + +#: forum/const.py:118 +msgid "question_answered" +msgstr "" + +#: forum/const.py:119 +msgid "question_commented" +msgstr "" + +#: forum/const.py:120 +msgid "answer_commented" +msgstr "" + +#: forum/const.py:121 +msgid "answer_accepted" +msgstr "" + +#: forum/const.py:125 +msgid "[closed]" +msgstr "" + +#: forum/const.py:126 +msgid "[deleted]" +msgstr "" + +#: forum/const.py:127 forum/views/readers.py:378 forum/views/readers.py:397 +msgid "initial version" +msgstr "" + +#: forum/const.py:128 +msgid "retagged" +msgstr "" + +#: forum/const.py:132 +msgid "exclude ignored tags" +msgstr "" + +#: forum/const.py:132 +msgid "allow only selected tags" +msgstr "" + +#: forum/feed.py:18 +msgid " - " +msgstr "" + +#: forum/feed.py:18 +msgid "latest questions" +msgstr "" + +#: forum/forms.py:23 forum/skins/default/templates/answer_edit_tips.html:35 +#: forum/skins/default/templates/answer_edit_tips.html:39 +#: forum/skins/default/templates/question_edit_tips.html:32 +#: forum/skins/default/templates/question_edit_tips.html:37 +msgid "title" +msgstr "" + +#: forum/forms.py:24 +msgid "please enter a descriptive title for your question" +msgstr "" + +#: forum/forms.py:29 +msgid "title must be > 10 characters" +msgstr "" + +#: forum/forms.py:38 +msgid "content" +msgstr "" + +#: forum/forms.py:44 +msgid "question content must be > 10 characters" +msgstr "" + +#: forum/forms.py:53 forum/skins/default/templates/header.html:31 +msgid "tags" +msgstr "" + +#: forum/forms.py:55 +msgid "" +"Tags are short keywords, with no spaces within. Up to five tags can be used." +msgstr "" + +#: forum/forms.py:62 forum/skins/default/templates/question_retag.html:39 +msgid "tags are required" +msgstr "" + +#: forum/forms.py:70 +#, python-format +msgid "please use %(tag_count)d tag or less" +msgid_plural "please use %(tag_count)d tags or less" +msgstr[0] "" +msgstr[1] "" + +#: forum/forms.py:79 +#, python-format +msgid "each tag must be shorter than %(max_chars)d character" +msgid_plural "each tag must be shorter than %(max_shars)d characters" +msgstr[0] "" +msgstr[1] "" + +#: forum/forms.py:87 +msgid "use-these-chars-in-tags" +msgstr "" + +#: forum/forms.py:97 +#: forum/skins/default/templates/post_contributor_info.html:7 +#: forum/skins/default/templates/question_summary_list_roll.html:26 +#: forum/skins/default/templates/question_summary_list_roll.html:38 +msgid "community wiki" +msgstr "" + +#: forum/forms.py:98 +msgid "" +"if you choose community wiki option, the question and answer do not generate " +"points and name of author will not be shown" +msgstr "" + +#: forum/forms.py:114 +msgid "update summary:" +msgstr "" + +#: forum/forms.py:115 +msgid "" +"enter a brief summary of your revision (e.g. fixed spelling, grammar, " +"improved style, this field is optional)" +msgstr "" + +#: forum/forms.py:118 +msgid "Automatically accept user's contributions for the email updates" +msgstr "" + +#: forum/forms.py:205 +msgid "Your name:" +msgstr "" + +#: forum/forms.py:206 +msgid "Email (not shared with anyone):" +msgstr "" + +#: forum/forms.py:207 +msgid "Your message:" +msgstr "" + +#: forum/forms.py:290 +msgid "this email does not have to be linked to gravatar" +msgstr "" + +#: forum/forms.py:292 +msgid "Screen name" +msgstr "" + +#: forum/forms.py:293 +msgid "Real name" +msgstr "" + +#: forum/forms.py:294 +msgid "Website" +msgstr "" + +#: forum/forms.py:295 +msgid "Location" +msgstr "" + +#: forum/forms.py:296 +msgid "Date of birth" +msgstr "" + +#: forum/forms.py:296 +msgid "will not be shown, used to calculate age, format: YYYY-MM-DD" +msgstr "" + +#: forum/forms.py:297 forum/skins/default/templates/account_settings.html:21 +#: forum/skins/default/templates/authopenid/settings.html:21 +msgid "Profile" +msgstr "" + +#: forum/forms.py:328 forum/forms.py:329 +msgid "this email has already been registered, please use another one" +msgstr "" + +#: forum/forms.py:335 +msgid "Choose email tag filter" +msgstr "" + +#: forum/forms.py:351 forum/forms.py:352 +msgid "weekly" +msgstr "" + +#: forum/forms.py:351 forum/forms.py:352 +msgid "no email" +msgstr "" + +#: forum/forms.py:352 +msgid "daily" +msgstr "" + +#: forum/forms.py:367 +msgid "Asked by me" +msgstr "" + +#: forum/forms.py:370 +msgid "Answered by me" +msgstr "" + +#: forum/forms.py:373 +msgid "Individually selected" +msgstr "" + +#: forum/forms.py:376 +msgid "Entire forum (tag filtered)" +msgstr "" + +#: forum/forms.py:430 forum/authentication/forms.py:41 +msgid "okay, let's try!" +msgstr "" + +#: forum/forms.py:431 +msgid "no community email please, thanks" +msgstr "" + +#: forum/forms.py:434 forum/authentication/forms.py:45 +msgid "please choose one of the options above" +msgstr "" + +#: forum/urls.py:28 +msgid "upfiles/" +msgstr "" + +#: forum/urls.py:33 +msgid "about/" +msgstr "" + +#: forum/urls.py:34 +msgid "faq/" +msgstr "" + +#: forum/urls.py:35 +msgid "privacy/" +msgstr "" + +#: forum/urls.py:36 +msgid "logout/" +msgstr "" + +#: forum/urls.py:37 forum/urls.py:38 forum/urls.py:39 forum/urls.py:56 +msgid "answers/" +msgstr "" + +#: forum/urls.py:37 forum/urls.py:49 forum/urls.py:52 forum/urls.py:56 +msgid "comments/" +msgstr "" + +#: forum/urls.py:38 forum/urls.py:43 forum/urls.py:78 +#: forum/skins/default/templates/user_info.html:47 +msgid "edit/" +msgstr "" + +#: forum/urls.py:39 forum/urls.py:48 +msgid "revisions/" +msgstr "" + +#: forum/urls.py:40 forum/urls.py:41 forum/urls.py:42 forum/urls.py:43 +#: forum/urls.py:44 forum/urls.py:45 forum/urls.py:46 forum/urls.py:47 +#: forum/urls.py:48 forum/urls.py:49 forum/urls.py:52 +msgid "questions/" +msgstr "" + +#: forum/urls.py:41 forum_modules/books/urls.py:8 +msgid "ask/" +msgstr "" + +#: forum/urls.py:42 +msgid "unanswered/" +msgstr "" + +#: forum/urls.py:44 +msgid "close/" +msgstr "" + +#: forum/urls.py:45 +msgid "reopen/" +msgstr "" + +#: forum/urls.py:46 +msgid "answer/" +msgstr "" + +#: forum/urls.py:47 +msgid "vote/" +msgstr "" + +#: forum/urls.py:50 +msgid "command/" +msgstr "" + +#: forum/urls.py:60 forum/views/readers.py:249 +msgid "question/" +msgstr "" + +#: forum/urls.py:61 forum/urls.py:62 +msgid "tags/" +msgstr "" + +#: forum/urls.py:64 forum/urls.py:68 +msgid "mark-tag/" +msgstr "" + +#: forum/urls.py:64 +msgid "interesting/" +msgstr "" + +#: forum/urls.py:68 +msgid "ignored/" +msgstr "" + +#: forum/urls.py:72 +msgid "unmark-tag/" +msgstr "" + +#: forum/urls.py:76 forum/urls.py:78 forum/urls.py:79 +msgid "users/" +msgstr "" + +#: forum/urls.py:77 +msgid "moderate-user/" +msgstr "" + +#: forum/urls.py:80 forum/urls.py:81 +msgid "badges/" +msgstr "" + +#: forum/urls.py:82 +msgid "messages/" +msgstr "" + +#: forum/urls.py:82 +msgid "markread/" +msgstr "" + +#: forum/urls.py:84 +msgid "nimda/" +msgstr "" + +#: forum/urls.py:86 +msgid "upload/" +msgstr "" + +#: forum/urls.py:87 +msgid "search/" +msgstr "" + +#: forum/urls.py:88 +msgid "feedback/" +msgstr "" + +#: forum/urls.py:89 forum/urls.py:90 +msgid "account/" +msgstr "" + +#: forum/authentication/forms.py:22 +msgid "Your account email" +msgstr "" + +#: forum/authentication/forms.py:24 +msgid "You cannot leave this field blank" +msgstr "" + +#: forum/authentication/forms.py:25 forum/utils/forms.py:111 +msgid "please enter a valid email address" +msgstr "" + +#: forum/authentication/forms.py:33 +msgid "Sorry, but this email is not on our database." +msgstr "" + +#: forum/authentication/forms.py:42 +msgid "no OSQA community email please, thanks" +msgstr "" + +#: forum/management/commands/send_email_alerts.py:236 +msgid "email update message subject" +msgstr "" + +#: forum/management/commands/send_email_alerts.py:238 +#, python-format +msgid "%(name)s, this is an update message header for a question" +msgid_plural "%(name)s, this is an update message header for %(num)d questions" +msgstr[0] "" +msgstr[1] "" + +#: forum/management/commands/send_email_alerts.py:255 +msgid "new question" +msgstr "" + +#: forum/management/commands/send_email_alerts.py:272 +msgid "" +"Please visit the forum and see what's new! Could you spread the word about " +"it - can somebody you know help answering those questions or benefit from " +"posting one?" +msgstr "" + +#: forum/management/commands/send_email_alerts.py:284 +msgid "" +"Your most frequent subscription setting is 'daily' on selected questions. If " +"you are receiving more than one email per dayplease tell about this issue to " +"the forum administrator." +msgstr "" + +#: forum/management/commands/send_email_alerts.py:290 +msgid "" +"Your most frequent subscription setting is 'weekly' if you are receiving " +"this email more than once a week please report this issue to the forum " +"administrator." +msgstr "" + +#: forum/management/commands/send_email_alerts.py:296 +msgid "" +"There is a chance that you may be receiving links seen before - due to a " +"technicality that will eventually go away. " +msgstr "" + +#: forum/management/commands/send_email_alerts.py:311 +#, python-format +msgid "" +"go to %(link)s to change frequency of email updates or %(email)s " +"administrator" +msgstr "" + +#: forum/middleware/anon_user.py:34 +#, python-format +msgid "First time here? Check out the <a href=\"%s\">FAQ</a>!" +msgstr "" + +#: forum/models/question.py:481 +#, python-format +msgid "%(author)s modified the question" +msgstr "" + +#: forum/models/question.py:485 +#, python-format +msgid "%(people)s posted %(new_answer_count)s new answers" +msgstr "" + +#: forum/models/question.py:490 +#, python-format +msgid "%(people)s commented the question" +msgstr "" + +#: forum/models/question.py:495 +#, python-format +msgid "%(people)s commented answers" +msgstr "" + +#: forum/models/question.py:497 +#, python-format +msgid "%(people)s commented an answer" +msgstr "" + +#: forum/models/repute.py:13 forum/skins/default/templates/badges.html:53 +msgid "gold" +msgstr "" + +#: forum/models/repute.py:14 forum/skins/default/templates/badges.html:61 +msgid "silver" +msgstr "" + +#: forum/models/repute.py:15 forum/skins/default/templates/badges.html:68 +msgid "bronze" +msgstr "" + +#: forum/models/tag.py:81 +msgid "interesting" +msgstr "" + +#: forum/models/tag.py:81 +msgid "ignored" +msgstr "" + +#: forum/models/user.py:36 +msgid "Entire forum" +msgstr "" + +#: forum/models/user.py:37 +msgid "Questions that I asked" +msgstr "" + +#: forum/models/user.py:38 +msgid "Questions that I answered" +msgstr "" + +#: forum/models/user.py:39 +msgid "Individually selected questions" +msgstr "" + +#: forum/models/user.py:42 +msgid "Weekly" +msgstr "" + +#: forum/models/user.py:43 +msgid "Daily" +msgstr "" + +#: forum/models/user.py:44 +msgid "No email" +msgstr "" + +#: forum/skins/default/templates/404.html:24 +msgid "Sorry, could not find the page you requested." +msgstr "" + +#: forum/skins/default/templates/404.html:26 +msgid "This might have happened for the following reasons:" +msgstr "" + +#: forum/skins/default/templates/404.html:28 +msgid "this question or answer has been deleted;" +msgstr "" + +#: forum/skins/default/templates/404.html:29 +msgid "url has error - please check it;" +msgstr "" + +#: forum/skins/default/templates/404.html:30 +msgid "" +"the page you tried to visit is protected or you don't have sufficient " +"points, see" +msgstr "" + +#: forum/skins/default/templates/404.html:31 +msgid "if you believe this error 404 should not have occured, please" +msgstr "" + +#: forum/skins/default/templates/404.html:32 +msgid "report this problem" +msgstr "" + +#: forum/skins/default/templates/404.html:41 +#: forum/skins/default/templates/500.html:27 +msgid "back to previous page" +msgstr "" + +#: forum/skins/default/templates/404.html:42 +#: forum/skins/default/templates/questions.html:52 +msgid "see all questions" +msgstr "" + +#: forum/skins/default/templates/404.html:43 +#: forum/skins/default/templates/index.html:65 +msgid "see all tags" +msgstr "" + +#: forum/skins/default/templates/500.html:22 +msgid "sorry, system error" +msgstr "" + +#: forum/skins/default/templates/500.html:24 +msgid "system error log is recorded, error will be fixed as soon as possible" +msgstr "" + +#: forum/skins/default/templates/500.html:25 +msgid "please report the error to the site administrators if you wish" +msgstr "" + +#: forum/skins/default/templates/500.html:28 +msgid "see latest questions" +msgstr "" + +#: forum/skins/default/templates/500.html:29 +msgid "see tags" +msgstr "" + +#: forum/skins/default/templates/about.html:6 +#: forum/skins/default/templates/about.html:11 +msgid "About" +msgstr "" + +#: forum/skins/default/templates/account_settings.html:4 +#: forum/skins/default/templates/authopenid/settings.html:4 +msgid "Account functions" +msgstr "" + +#: forum/skins/default/templates/account_settings.html:29 +#: forum/skins/default/templates/authopenid/changepw.html:5 +#: forum/skins/default/templates/authopenid/changepw.html:14 +#: forum/skins/default/templates/authopenid/settings.html:29 +msgid "Change password" +msgstr "" + +#: forum/skins/default/templates/account_settings.html:30 +#: forum/skins/default/templates/authopenid/settings.html:30 +msgid "Give your account a new password." +msgstr "" + +#: forum/skins/default/templates/account_settings.html:32 +#: forum/skins/default/templates/authopenid/settings.html:31 +msgid "Change email " +msgstr "" + +#: forum/skins/default/templates/account_settings.html:33 +#: forum/skins/default/templates/authopenid/settings.html:32 +msgid "Add or update the email address associated with your account." +msgstr "" + +#: forum/skins/default/templates/account_settings.html:35 +#: forum/skins/default/templates/authopenid/changeopenid.html:4 +#: forum/skins/default/templates/authopenid/changeopenid.html:30 +#: forum/skins/default/templates/authopenid/settings.html:34 +msgid "Change OpenID" +msgstr "" + +#: forum/skins/default/templates/account_settings.html:36 +#: forum/skins/default/templates/authopenid/settings.html:35 +msgid "Change openid associated to your account" +msgstr "" + +#: forum/skins/default/templates/account_settings.html:39 +#: forum/skins/default/templates/authopenid/delete.html:4 +#: forum/skins/default/templates/authopenid/settings.html:38 +msgid "Delete account" +msgstr "" + +#: forum/skins/default/templates/account_settings.html:40 +#: forum/skins/default/templates/authopenid/settings.html:39 +msgid "Erase your username and all your data from website" +msgstr "" + +#: forum/skins/default/templates/answer_edit.html:5 +#: forum/skins/default/templates/answer_edit.html:48 +msgid "Edit answer" +msgstr "" + +#: forum/skins/default/templates/answer_edit.html:25 +#: forum/skins/default/templates/answer_edit.html:28 +#: forum/skins/default/templates/ask.html:26 +#: forum/skins/default/templates/ask.html:29 +#: forum/skins/default/templates/question.html:46 +#: forum/skins/default/templates/question.html:49 +#: forum/skins/default/templates/question_edit.html:25 +#: forum/skins/default/templates/question_edit.html:28 +msgid "hide preview" +msgstr "" + +#: forum/skins/default/templates/answer_edit.html:28 +#: forum/skins/default/templates/ask.html:29 +#: forum/skins/default/templates/question.html:49 +#: forum/skins/default/templates/question_edit.html:28 +msgid "show preview" +msgstr "" + +#: forum/skins/default/templates/answer_edit.html:48 +#: forum/skins/default/templates/question_edit.html:66 +#: forum/skins/default/templates/question_retag.html:53 +#: forum/skins/default/templates/revisions_answer.html:38 +#: forum/skins/default/templates/revisions_question.html:38 +msgid "back" +msgstr "" + +#: forum/skins/default/templates/answer_edit.html:53 +#: forum/skins/default/templates/question_edit.html:71 +#: forum/skins/default/templates/revisions_answer.html:52 +#: forum/skins/default/templates/revisions_question.html:52 +msgid "revision" +msgstr "" + +#: forum/skins/default/templates/answer_edit.html:56 +#: forum/skins/default/templates/question_edit.html:75 +msgid "select revision" +msgstr "" + +#: forum/skins/default/templates/answer_edit.html:63 +#: forum/skins/default/templates/ask.html:98 +#: forum/skins/default/templates/ask_form.html:39 +#: forum/skins/default/templates/question.html:433 +#: forum/skins/default/templates/question_edit.html:92 +msgid "Toggle the real time Markdown editor preview" +msgstr "" + +#: forum/skins/default/templates/answer_edit.html:63 +#: forum/skins/default/templates/ask.html:98 +#: forum/skins/default/templates/ask_form.html:39 +#: forum/skins/default/templates/question.html:434 +#: forum/skins/default/templates/question_edit.html:92 +msgid "toggle preview" +msgstr "" + +#: forum/skins/default/templates/answer_edit.html:72 +#: forum/skins/default/templates/question_edit.html:118 +#: forum/skins/default/templates/question_retag.html:74 +msgid "Save edit" +msgstr "" + +#: forum/skins/default/templates/answer_edit.html:73 +#: forum/skins/default/templates/close.html:29 +#: forum/skins/default/templates/feedback.html:50 +#: forum/skins/default/templates/question_edit.html:119 +#: forum/skins/default/templates/question_retag.html:75 +#: forum/skins/default/templates/reopen.html:30 +#: forum/skins/default/templates/user_edit.html:84 +#: forum/skins/default/templates/authopenid/changeemail.html:40 +msgid "Cancel" +msgstr "" + +#: forum/skins/default/templates/answer_edit_tips.html:4 +msgid "answer tips" +msgstr "" + +#: forum/skins/default/templates/answer_edit_tips.html:7 +msgid "please make your answer relevant to this community" +msgstr "" + +#: forum/skins/default/templates/answer_edit_tips.html:10 +msgid "try to give an answer, rather than engage into a discussion" +msgstr "" + +#: forum/skins/default/templates/answer_edit_tips.html:13 +msgid "please try to provide details" +msgstr "" + +#: forum/skins/default/templates/answer_edit_tips.html:16 +#: forum/skins/default/templates/question_edit_tips.html:13 +msgid "be clear and concise" +msgstr "" + +#: forum/skins/default/templates/answer_edit_tips.html:20 +#: forum/skins/default/templates/question_edit_tips.html:17 +msgid "see frequently asked questions" +msgstr "" + +#: forum/skins/default/templates/answer_edit_tips.html:26 +#: forum/skins/default/templates/question_edit_tips.html:23 +msgid "Markdown tips" +msgstr "" + +#: forum/skins/default/templates/answer_edit_tips.html:29 +#: forum/skins/default/templates/question_edit_tips.html:26 +msgid "*italic* or __italic__" +msgstr "" + +#: forum/skins/default/templates/answer_edit_tips.html:32 +#: forum/skins/default/templates/question_edit_tips.html:29 +msgid "**bold** or __bold__" +msgstr "" + +#: forum/skins/default/templates/answer_edit_tips.html:35 +#: forum/skins/default/templates/question_edit_tips.html:32 +msgid "link" +msgstr "" + +#: forum/skins/default/templates/answer_edit_tips.html:35 +#: forum/skins/default/templates/answer_edit_tips.html:39 +#: forum/skins/default/templates/question_edit_tips.html:32 +#: forum/skins/default/templates/question_edit_tips.html:37 +msgid "text" +msgstr "" + +#: forum/skins/default/templates/answer_edit_tips.html:39 +#: forum/skins/default/templates/question_edit_tips.html:37 +msgid "image" +msgstr "" + +#: forum/skins/default/templates/answer_edit_tips.html:43 +#: forum/skins/default/templates/question_edit_tips.html:41 +msgid "numbered list:" +msgstr "" + +#: forum/skins/default/templates/answer_edit_tips.html:48 +#: forum/skins/default/templates/question_edit_tips.html:46 +msgid "basic HTML tags are also supported" +msgstr "" + +#: forum/skins/default/templates/answer_edit_tips.html:52 +#: forum/skins/default/templates/question_edit_tips.html:50 +msgid "learn more about Markdown" +msgstr "" + +#: forum/skins/default/templates/ask.html:5 +#: forum/skins/default/templates/ask.html:62 +msgid "Ask a question" +msgstr "" + +#: forum/skins/default/templates/ask.html:69 +#: forum/skins/default/templates/ask_form.html:11 +msgid "login to post question info" +msgstr "" + +#: forum/skins/default/templates/ask.html:75 +#, python-format +msgid "" +"must have valid %(email)s to post, \n" +" see %(email_validation_faq_url)s\n" +" " +msgstr "" + +#: forum/skins/default/templates/ask.html:113 +#: forum/skins/default/templates/ask_form.html:54 +msgid "(required)" +msgstr "" + +#: forum/skins/default/templates/ask.html:120 +#: forum/skins/default/templates/ask_form.html:61 +msgid "Login/signup to post your question" +msgstr "" + +#: forum/skins/default/templates/ask.html:122 +#: forum/skins/default/templates/ask_form.html:63 +msgid "Ask your question" +msgstr "" + +#: forum/skins/default/templates/ask_form.html:15 +#, python-format +msgid "" +"must have valid %(email)s to post, \n" +" see %(email_validation_faq_url)s\n" +" " +msgstr "" + +#: forum/skins/default/templates/badge.html:6 +#: forum/skins/default/templates/badge.html:17 +msgid "Badge" +msgstr "" + +#: forum/skins/default/templates/badge.html:26 +msgid "The users have been awarded with badges:" +msgstr "" + +#: forum/skins/default/templates/badges.html:6 +msgid "Badges summary" +msgstr "" + +#: forum/skins/default/templates/badges.html:17 +msgid "Badges" +msgstr "" + +#: forum/skins/default/templates/badges.html:21 +msgid "Community gives you awards for your questions, answers and votes." +msgstr "" + +#: forum/skins/default/templates/badges.html:22 +#, python-format +msgid "" +"Below is the list of available badges and number \n" +" of times each type of badge has been awarded. Give us feedback at %" +"(feedback_faq_url)s.\n" +" " +msgstr "" + +#: forum/skins/default/templates/badges.html:50 +msgid "Community badges" +msgstr "" + +#: forum/skins/default/templates/badges.html:56 +msgid "gold badge description" +msgstr "" + +#: forum/skins/default/templates/badges.html:64 +msgid "silver badge description" +msgstr "" + +#: forum/skins/default/templates/badges.html:67 +msgid "bronze badge: often given as a special honor" +msgstr "" + +#: forum/skins/default/templates/badges.html:71 +msgid "bronze badge description" +msgstr "" + +#: forum/skins/default/templates/book.html:7 +msgid "reading channel" +msgstr "" + +#: forum/skins/default/templates/book.html:26 +msgid "[author]" +msgstr "" + +#: forum/skins/default/templates/book.html:30 +msgid "[publisher]" +msgstr "" + +#: forum/skins/default/templates/book.html:34 +msgid "[publication date]" +msgstr "" + +#: forum/skins/default/templates/book.html:38 +msgid "[price]" +msgstr "" + +#: forum/skins/default/templates/book.html:39 +msgid "currency unit" +msgstr "" + +#: forum/skins/default/templates/book.html:42 +msgid "[pages]" +msgstr "" + +#: forum/skins/default/templates/book.html:43 +msgid "pages abbreviation" +msgstr "" + +#: forum/skins/default/templates/book.html:46 +msgid "[tags]" +msgstr "" + +#: forum/skins/default/templates/book.html:56 +msgid "author blog" +msgstr "" + +#: forum/skins/default/templates/book.html:62 +msgid "book directory" +msgstr "" + +#: forum/skins/default/templates/book.html:66 +msgid "buy online" +msgstr "" + +#: forum/skins/default/templates/book.html:79 +msgid "reader questions" +msgstr "" + +#: forum/skins/default/templates/book.html:82 +msgid "ask the author" +msgstr "" + +#: forum/skins/default/templates/book.html:88 +#: forum/skins/default/templates/book.html:93 +#: forum/skins/default/templates/users_questions.html:18 +msgid "this question was selected as favorite" +msgstr "" + +#: forum/skins/default/templates/book.html:88 +#: forum/skins/default/templates/book.html:93 +#: forum/skins/default/templates/users_questions.html:11 +#: forum/skins/default/templates/users_questions.html:18 +msgid "number of times" +msgstr "" + +#: forum/skins/default/templates/book.html:105 +#: forum/skins/default/templates/index_.html:40 +#: forum/skins/default/templates/question_summary_list_roll.html:14 +msgid "votes" +msgstr "" + +#: forum/skins/default/templates/book.html:108 +msgid "the answer has been accepted to be correct" +msgstr "" + +#: forum/skins/default/templates/book.html:115 +#: forum/skins/default/templates/index_.html:48 +#: forum/skins/default/templates/question_summary_list_roll.html:15 +msgid "views" +msgstr "" + +#: forum/skins/default/templates/book.html:125 +#: forum/skins/default/templates/index_.html:63 +#: forum/skins/default/templates/question.html:136 +#: forum/skins/default/templates/question_list.html:19 +#: forum/skins/default/templates/question_summary_list_roll.html:52 +#: forum/skins/default/templates/tags.html:50 +#: forum/skins/default/templates/users_questions.html:34 +#, python-format +msgid "see questions tagged '%(tag)s'" +msgstr "" + +#: forum/skins/default/templates/book.html:147 +msgid "subscribe to book RSS feed" +msgstr "" + +#: forum/skins/default/templates/book.html:147 +#: forum/skins/default/templates/index.html:88 +#: forum/skins/default/templates/index_.html:115 +msgid "subscribe to the questions feed" +msgstr "" + +#: forum/skins/default/templates/close.html:6 +#: forum/skins/default/templates/close.html:16 +msgid "Close question" +msgstr "" + +#: forum/skins/default/templates/close.html:19 +msgid "Close the question" +msgstr "" + +#: forum/skins/default/templates/close.html:25 +msgid "Reasons" +msgstr "" + +#: forum/skins/default/templates/close.html:28 +msgid "OK to close" +msgstr "" + +#: forum/skins/default/templates/email_base.html:11 +msgid "home" +msgstr "" + +#: forum/skins/default/templates/faq.html:11 +msgid "Frequently Asked Questions " +msgstr "" + +#: forum/skins/default/templates/faq.html:16 +msgid "What kinds of questions can I ask here?" +msgstr "" + +#: forum/skins/default/templates/faq.html:17 +msgid "" +"Most importanly - questions should be <strong>relevant</strong> to this " +"community." +msgstr "" + +#: forum/skins/default/templates/faq.html:18 +msgid "" +"Before asking the question - please make sure to use search to see whether " +"your question has alredy been answered." +msgstr "" + +#: forum/skins/default/templates/faq.html:21 +msgid "What questions should I avoid asking?" +msgstr "" + +#: forum/skins/default/templates/faq.html:22 +msgid "" +"Please avoid asking questions that are not relevant to this community, too " +"subjective and argumentative." +msgstr "" + +#: forum/skins/default/templates/faq.html:27 +msgid "What should I avoid in my answers?" +msgstr "" + +#: forum/skins/default/templates/faq.html:28 +msgid "" +"is a Q&A site, not a discussion group. Therefore - please avoid having " +"discussions in your answers, comment facility allows some space for brief " +"discussions." +msgstr "" + +#: forum/skins/default/templates/faq.html:32 +msgid "Who moderates this community?" +msgstr "" + +#: forum/skins/default/templates/faq.html:33 +msgid "The short answer is: <strong>you</strong>." +msgstr "" + +#: forum/skins/default/templates/faq.html:34 +msgid "This website is moderated by the users." +msgstr "" + +#: forum/skins/default/templates/faq.html:35 +msgid "" +"The reputation system allows users earn the authorization to perform a " +"variety of moderation tasks." +msgstr "" + +#: forum/skins/default/templates/faq.html:40 +msgid "How does reputation system work?" +msgstr "" + +#: forum/skins/default/templates/faq.html:41 +msgid "Rep system summary" +msgstr "" + +#: forum/skins/default/templates/faq.html:42 +msgid "" +"For example, if you ask an interesting question or give a helpful answer, " +"your input will be upvoted. On the other hand if the answer is misleading - " +"it will be downvoted. Each vote in favor will generate <strong>10</strong> " +"points, each vote against will subtract <strong>2</strong> points. There is " +"a limit of <strong>200</strong> points that can be accumulated per question " +"or answer. The table below explains reputation point requirements for each " +"type of moderation task." +msgstr "" + +#: forum/skins/default/templates/faq.html:53 +#: forum/skins/default/templates/user_votes.html:15 +msgid "upvote" +msgstr "" + +#: forum/skins/default/templates/faq.html:57 +msgid "use tags" +msgstr "" + +#: forum/skins/default/templates/faq.html:62 +msgid "add comments" +msgstr "" + +#: forum/skins/default/templates/faq.html:66 +#: forum/skins/default/templates/user_votes.html:17 +msgid "downvote" +msgstr "" + +#: forum/skins/default/templates/faq.html:69 +msgid "open and close own questions" +msgstr "" + +#: forum/skins/default/templates/faq.html:73 +msgid "retag questions" +msgstr "" + +#: forum/skins/default/templates/faq.html:78 +msgid "edit community wiki questions" +msgstr "" + +#: forum/skins/default/templates/faq.html:83 +msgid "edit any answer" +msgstr "" + +#: forum/skins/default/templates/faq.html:87 +msgid "open any closed question" +msgstr "" + +#: forum/skins/default/templates/faq.html:91 +msgid "delete any comment" +msgstr "" + +#: forum/skins/default/templates/faq.html:95 +msgid "delete any questions and answers and perform other moderation tasks" +msgstr "" + +#: forum/skins/default/templates/faq.html:103 +msgid "how to validate email title" +msgstr "" + +#: forum/skins/default/templates/faq.html:105 +#, python-format +msgid "" +"how to validate email info with %(send_email_key_url)s %(gravatar_faq_url)s" +msgstr "" + +#: forum/skins/default/templates/faq.html:110 +msgid "what is gravatar" +msgstr "" + +#: forum/skins/default/templates/faq.html:111 +msgid "gravatar faq info" +msgstr "" + +#: forum/skins/default/templates/faq.html:114 +msgid "To register, do I need to create new password?" +msgstr "" + +#: forum/skins/default/templates/faq.html:115 +msgid "" +"No, you don't have to. You can login through any service that supports " +"OpenID, e.g. Google, Yahoo, AOL, etc." +msgstr "" + +#: forum/skins/default/templates/faq.html:116 +msgid "Login now!" +msgstr "" + +#: forum/skins/default/templates/faq.html:121 +msgid "Why other people can edit my questions/answers?" +msgstr "" + +#: forum/skins/default/templates/faq.html:122 +msgid "Goal of this site is..." +msgstr "" + +#: forum/skins/default/templates/faq.html:122 +msgid "" +"So questions and answers can be edited like wiki pages by experienced users " +"of this site and this improves the overall quality of the knowledge base " +"content." +msgstr "" + +#: forum/skins/default/templates/faq.html:123 +msgid "If this approach is not for you, we respect your choice." +msgstr "" + +#: forum/skins/default/templates/faq.html:127 +msgid "Still have questions?" +msgstr "" + +#: forum/skins/default/templates/faq.html:128 +#, python-format +msgid "" +"Please ask your question at %(ask_question_url)s, help make our community " +"better!" +msgstr "" + +#: forum/skins/default/templates/faq.html:130 +#: forum/skins/default/templates/header.html:30 +msgid "questions" +msgstr "" + +#: forum/skins/default/templates/faq.html:130 +#: forum/skins/default/templates/index.html:95 +#: forum/skins/default/templates/index_.html:122 +msgid "." +msgstr "" + +#: forum/skins/default/templates/feedback.html:6 +msgid "Feedback" +msgstr "" + +#: forum/skins/default/templates/feedback.html:11 +msgid "Give us your feedback!" +msgstr "" + +#: forum/skins/default/templates/feedback.html:17 +#, python-format +msgid "" +"\n" +" <span class='big strong'>Dear %(user_name)s</span>, we look " +"forward to hearing your feedback. \n" +" Please type and send us your message below.\n" +" " +msgstr "" + +#: forum/skins/default/templates/feedback.html:24 +msgid "" +"\n" +" <span class='big strong'>Dear visitor</span>, we look forward to " +"hearing your feedback.\n" +" Please type and send us your message below.\n" +" " +msgstr "" + +#: forum/skins/default/templates/feedback.html:41 +msgid "(this field is required)" +msgstr "" + +#: forum/skins/default/templates/feedback.html:49 +msgid "Send Feedback" +msgstr "" + +#: forum/skins/default/templates/feedback_email.txt:3 +#, python-format +msgid "" +"\n" +"Hello, this is a %(site_title)s forum feedback message\n" +msgstr "" + +#: forum/skins/default/templates/feedback_email.txt:9 +msgid "Sender is" +msgstr "" + +#: forum/skins/default/templates/feedback_email.txt:11 +#: forum/skins/default/templates/feedback_email.txt:14 +msgid "email" +msgstr "" + +#: forum/skins/default/templates/feedback_email.txt:13 +msgid "anonymous" +msgstr "" + +#: forum/skins/default/templates/feedback_email.txt:19 +msgid "Message body:" +msgstr "" + +#: forum/skins/default/templates/footer.html:8 +#: forum/skins/default/templates/header.html:17 +#: forum/skins/default/templates/index.html:46 +#: forum/skins/default/templates/index_.html:77 +msgid "about" +msgstr "" + +#: forum/skins/default/templates/footer.html:9 +#: forum/skins/default/templates/header.html:18 +#: forum/skins/default/templates/index.html:47 +#: forum/skins/default/templates/index_.html:78 +#: forum/skins/default/templates/question_edit_tips.html:17 +msgid "faq" +msgstr "" + +#: forum/skins/default/templates/footer.html:10 +msgid "privacy policy" +msgstr "" + +#: forum/skins/default/templates/footer.html:19 +msgid "give feedback" +msgstr "" + +#: forum/skins/default/templates/header.html:13 +msgid "logout" +msgstr "" + +#: forum/skins/default/templates/header.html:15 +msgid "login" +msgstr "" + +#: forum/skins/default/templates/header.html:25 +msgid "back to home page" +msgstr "" + +#: forum/skins/default/templates/header.html:32 +msgid "users" +msgstr "" + +#: forum/skins/default/templates/header.html:34 +msgid "books" +msgstr "" + +#: forum/skins/default/templates/header.html:36 +#: forum/templatetags/extra_tags.py:174 forum/templatetags/extra_tags.py:203 +msgid "badges" +msgstr "" + +#: forum/skins/default/templates/header.html:37 +#: forum/skins/default/templates/header.html:41 +msgid "ask a question" +msgstr "" + +#: forum/skins/default/templates/header.html:39 +msgid "unanswered questions" +msgstr "" + +#: forum/skins/default/templates/index.html:9 +#: forum/skins/default/templates/index_.html:8 +msgid "Home" +msgstr "" + +#: forum/skins/default/templates/index.html:26 +#: forum/skins/default/templates/index_.html:25 +#: forum/skins/default/templates/questions.html:8 +msgid "Questions" +msgstr "" + +#: forum/skins/default/templates/index.html:28 +#: forum/skins/default/templates/index_.html:27 +msgid "last updated questions" +msgstr "" + +#: forum/skins/default/templates/index.html:29 +#: forum/skins/default/templates/index_.html:28 +msgid "hottest questions" +msgstr "" + +#: forum/skins/default/templates/index.html:30 +#: forum/skins/default/templates/index_.html:29 +msgid "most voted questions" +msgstr "" + +#: forum/skins/default/templates/index.html:31 +#: forum/skins/default/templates/index_.html:30 +msgid "all questions" +msgstr "" + +#: forum/skins/default/templates/index.html:43 +#: forum/skins/default/templates/index_.html:74 +msgid "welcome to website" +msgstr "" + +#: forum/skins/default/templates/index.html:54 +#: forum/skins/default/templates/index_.html:85 +msgid "Recent tags" +msgstr "" + +#: forum/skins/default/templates/index.html:60 +#: forum/skins/default/templates/index_.html:90 +#, python-format +msgid "see questions tagged '%(tagname)s'" +msgstr "" + +#: forum/skins/default/templates/index.html:70 +#: forum/skins/default/templates/index_.html:99 +msgid "Recent awards" +msgstr "" + +#: forum/skins/default/templates/index.html:83 +#: forum/skins/default/templates/index_.html:110 +msgid "all awards" +msgstr "" + +#: forum/skins/default/templates/index.html:88 +#: forum/skins/default/templates/index_.html:115 +msgid "subscribe to last 30 questions by RSS" +msgstr "" + +#: forum/skins/default/templates/index.html:95 +#: forum/skins/default/templates/index_.html:122 +msgid "Still looking for more? See" +msgstr "" + +#: forum/skins/default/templates/index.html:95 +#: forum/skins/default/templates/index_.html:122 +msgid "complete list of questions" +msgstr "" + +#: forum/skins/default/templates/index.html:95 +#: forum/skins/default/templates/index_.html:122 +#: forum/skins/default/templates/authopenid/signup.html:28 +msgid "or" +msgstr "" + +#: forum/skins/default/templates/index.html:95 +#: forum/skins/default/templates/index_.html:94 +#: forum/skins/default/templates/index_.html:122 +msgid "popular tags" +msgstr "" + +#: forum/skins/default/templates/index.html:95 +#: forum/skins/default/templates/index_.html:122 +msgid "Please help us answer" +msgstr "" + +#: forum/skins/default/templates/index.html:95 +#: forum/skins/default/templates/index_.html:122 +msgid "list of unanswered questions" +msgstr "" + +#: forum/skins/default/templates/index_.html:42 +#: forum/skins/default/templates/question_counter_widget.html:21 +msgid "this answer has been accepted to be correct" +msgstr "" + +#: forum/skins/default/templates/index_.html:44 +#: forum/skins/default/templates/question_summary_list_roll.html:13 +msgid "answers" +msgstr "" + +#: forum/skins/default/templates/input_bar.html:33 +msgid "search" +msgstr "" + +#: forum/skins/default/templates/logout.html:6 +#: forum/skins/default/templates/logout.html:16 +msgid "Logout" +msgstr "" + +#: forum/skins/default/templates/logout.html:19 +msgid "" +"As a registered user you can login with your OpenID, log out of the site or " +"permanently remove your account." +msgstr "" + +#: forum/skins/default/templates/logout.html:20 +msgid "Logout now" +msgstr "" + +#: forum/skins/default/templates/notarobot.html:3 +msgid "Please prove that you are a Human Being" +msgstr "" + +#: forum/skins/default/templates/notarobot.html:10 +msgid "I am a Human Being" +msgstr "" + +#: forum/skins/default/templates/pagesize.html:6 +msgid "posts per page" +msgstr "" + +#: forum/skins/default/templates/paginator.html:6 +#: forum/skins/default/templates/paginator.html:7 +msgid "previous" +msgstr "" + +#: forum/skins/default/templates/paginator.html:19 +msgid "current page" +msgstr "" + +#: forum/skins/default/templates/paginator.html:22 +#: forum/skins/default/templates/paginator.html:29 +msgid "page number " +msgstr "" + +#: forum/skins/default/templates/paginator.html:22 +#: forum/skins/default/templates/paginator.html:29 +msgid "number - make blank in english" +msgstr "" + +#: forum/skins/default/templates/paginator.html:33 +msgid "next page" +msgstr "" + +#: forum/skins/default/templates/post_contributor_info.html:9 +#, python-format +msgid "" +"\n" +" one revision\n" +" " +msgid_plural "" +"\n" +" %(rev_count)s revisions\n" +" " +msgstr[0] "" +msgstr[1] "" + +#: forum/skins/default/templates/post_contributor_info.html:19 +msgid "asked" +msgstr "" + +#: forum/skins/default/templates/post_contributor_info.html:22 +msgid "answered" +msgstr "" + +#: forum/skins/default/templates/post_contributor_info.html:24 +msgid "posted" +msgstr "" + +#: forum/skins/default/templates/post_contributor_info.html:45 +msgid "updated" +msgstr "" + +#: forum/skins/default/templates/privacy.html:6 +#: forum/skins/default/templates/privacy.html:11 +msgid "Privacy policy" +msgstr "" + +#: forum/skins/default/templates/privacy.html:15 +msgid "general message about privacy" +msgstr "" + +#: forum/skins/default/templates/privacy.html:18 +msgid "Site Visitors" +msgstr "" + +#: forum/skins/default/templates/privacy.html:20 +msgid "what technical information is collected about visitors" +msgstr "" + +#: forum/skins/default/templates/privacy.html:23 +msgid "Personal Information" +msgstr "" + +#: forum/skins/default/templates/privacy.html:25 +msgid "details on personal information policies" +msgstr "" + +#: forum/skins/default/templates/privacy.html:28 +msgid "Other Services" +msgstr "" + +#: forum/skins/default/templates/privacy.html:30 +msgid "details on sharing data with third parties" +msgstr "" + +#: forum/skins/default/templates/privacy.html:35 +msgid "cookie policy details" +msgstr "" + +#: forum/skins/default/templates/privacy.html:37 +msgid "Policy Changes" +msgstr "" + +#: forum/skins/default/templates/privacy.html:38 +msgid "how privacy policies can be changed" +msgstr "" + +#: forum/skins/default/templates/question.html:78 +#: forum/skins/default/templates/question.html:79 +#: forum/skins/default/templates/question.html:95 +#: forum/skins/default/templates/question.html:97 +msgid "i like this post (click again to cancel)" +msgstr "" + +#: forum/skins/default/templates/question.html:81 +#: forum/skins/default/templates/question.html:99 +#: forum/skins/default/templates/question.html:258 +msgid "current number of votes" +msgstr "" + +#: forum/skins/default/templates/question.html:90 +#: forum/skins/default/templates/question.html:91 +#: forum/skins/default/templates/question.html:104 +#: forum/skins/default/templates/question.html:105 +msgid "i dont like this post (click again to cancel)" +msgstr "" + +#: forum/skins/default/templates/question.html:109 +#: forum/skins/default/templates/question.html:110 +msgid "mark this question as favorite (click again to cancel)" +msgstr "" + +#: forum/skins/default/templates/question.html:116 +#: forum/skins/default/templates/question.html:117 +msgid "remove favorite mark from this question (click again to restore mark)" +msgstr "" + +#: forum/skins/default/templates/question.html:141 +#: forum/skins/default/templates/question.html:295 +#: forum/skins/default/templates/revisions_answer.html:58 +#: forum/skins/default/templates/revisions_question.html:58 +msgid "edit" +msgstr "" + +#: forum/skins/default/templates/question.html:146 +msgid "reopen" +msgstr "" + +#: forum/skins/default/templates/question.html:150 +msgid "close" +msgstr "" + +#: forum/skins/default/templates/question.html:156 +#: forum/skins/default/templates/question.html:300 +msgid "" +"report as offensive (i.e containing spam, advertising, malicious text, etc.)" +msgstr "" + +#: forum/skins/default/templates/question.html:157 +#: forum/skins/default/templates/question.html:301 +msgid "flag offensive" +msgstr "" + +#: forum/skins/default/templates/question.html:165 +#: forum/skins/default/templates/question.html:312 +msgid "delete" +msgstr "" + +#: forum/skins/default/templates/question.html:183 +#: forum/skins/default/templates/question.html:332 +msgid "delete this comment" +msgstr "" + +#: forum/skins/default/templates/question.html:194 +#: forum/skins/default/templates/question.html:343 +msgid "add comment" +msgstr "" + +#: forum/skins/default/templates/question.html:198 +#, python-format +msgid "" +"\n" +" see <strong>one</strong> more \n" +" " +msgid_plural "" +"\n" +" see <strong>%(counter)s</strong> " +"more\n" +" " +msgstr[0] "" +msgstr[1] "" + +#: forum/skins/default/templates/question.html:204 +#, python-format +msgid "" +"\n" +" see <strong>one</strong> more " +"comment\n" +" " +msgid_plural "" +"\n" +" see <strong>%(counter)s</strong> " +"more comments\n" +" " +msgstr[0] "" +msgstr[1] "" + +#: forum/skins/default/templates/question.html:220 +#, python-format +msgid "" +"The question has been closed for the following reason \"%(close_reason)s\" by" +msgstr "" + +#: forum/skins/default/templates/question.html:222 +#, python-format +msgid "close date %(closed_at)s" +msgstr "" + +#: forum/skins/default/templates/question.html:230 +#, python-format +msgid "" +"\n" +" One Answer:\n" +" " +msgid_plural "" +"\n" +" %(counter)s Answers:\n" +" " +msgstr[0] "" +msgstr[1] "" + +#: forum/skins/default/templates/question.html:238 +msgid "oldest answers will be shown first" +msgstr "" + +#: forum/skins/default/templates/question.html:238 +msgid "oldest answers" +msgstr "" + +#: forum/skins/default/templates/question.html:240 +msgid "newest answers will be shown first" +msgstr "" + +#: forum/skins/default/templates/question.html:240 +msgid "newest answers" +msgstr "" + +#: forum/skins/default/templates/question.html:242 +msgid "most voted answers will be shown first" +msgstr "" + +#: forum/skins/default/templates/question.html:242 +msgid "popular answers" +msgstr "" + +#: forum/skins/default/templates/question.html:256 +#: forum/skins/default/templates/question.html:257 +msgid "i like this answer (click again to cancel)" +msgstr "" + +#: forum/skins/default/templates/question.html:263 +#: forum/skins/default/templates/question.html:264 +msgid "i dont like this answer (click again to cancel)" +msgstr "" + +#: forum/skins/default/templates/question.html:269 +#: forum/skins/default/templates/question.html:270 +msgid "mark this answer as favorite (click again to undo)" +msgstr "" + +#: forum/skins/default/templates/question.html:275 +#: forum/skins/default/templates/question.html:276 +msgid "the author of the question has selected this answer as correct" +msgstr "" + +#: forum/skins/default/templates/question.html:289 +msgid "answer permanent link" +msgstr "" + +#: forum/skins/default/templates/question.html:290 +msgid "permanent link" +msgstr "" + +#: forum/skins/default/templates/question.html:312 +msgid "undelete" +msgstr "" + +#: forum/skins/default/templates/question.html:347 +#, python-format +msgid "" +"\n" +" see <strong>one</" +"strong> more \n" +" " +msgid_plural "" +"\n" +" see <strong>%" +"(counter)s</strong> more\n" +" " +msgstr[0] "" +msgstr[1] "" + +#: forum/skins/default/templates/question.html:353 +#, python-format +msgid "" +"\n" +" see <strong>one</" +"strong> more comment\n" +" " +msgid_plural "" +"\n" +" see <strong>%" +"(counter)s</strong> more comments\n" +" " +msgstr[0] "" +msgstr[1] "" + +#: forum/skins/default/templates/question.html:379 +#: forum/skins/default/templates/question.html:382 +msgid "Notify me once a day when there are any new answers" +msgstr "" + +#: forum/skins/default/templates/question.html:385 +msgid "Notify me weekly when there are any new answers" +msgstr "" + +#: forum/skins/default/templates/question.html:390 +#, python-format +msgid "" +"You can always adjust frequency of email updates from your %(profile_url)s" +msgstr "" + +#: forum/skins/default/templates/question.html:395 +msgid "once you sign in you will be able to subscribe for any updates here" +msgstr "" + +#: forum/skins/default/templates/question.html:406 +msgid "Your answer" +msgstr "" + +#: forum/skins/default/templates/question.html:408 +msgid "Be the first one to answer this question!" +msgstr "" + +#: forum/skins/default/templates/question.html:414 +msgid "you can answer anonymously and then login" +msgstr "" + +#: forum/skins/default/templates/question.html:418 +msgid "answer your own question only to give an answer" +msgstr "" + +#: forum/skins/default/templates/question.html:420 +msgid "please only give an answer, no discussions" +msgstr "" + +#: forum/skins/default/templates/question.html:456 +msgid "Login/Signup to Post Your Answer" +msgstr "" + +#: forum/skins/default/templates/question.html:459 +msgid "Answer Your Own Question" +msgstr "" + +#: forum/skins/default/templates/question.html:461 +msgid "Answer the question" +msgstr "" + +#: forum/skins/default/templates/question.html:475 +msgid "Question tags" +msgstr "" + +#: forum/skins/default/templates/question.html:480 +#: forum/skins/default/templates/questions.html:246 +#: forum/skins/default/templates/tag_selector.html:11 +#: forum/skins/default/templates/tag_selector.html:28 +#, python-format +msgid "see questions tagged '%(tag_name)s'" +msgstr "" + +#: forum/skins/default/templates/question.html:486 +msgid "question asked" +msgstr "" + +#: forum/skins/default/templates/question.html:489 +msgid "question was seen" +msgstr "" + +#: forum/skins/default/templates/question.html:489 +msgid "times" +msgstr "" + +#: forum/skins/default/templates/question.html:492 +msgid "last updated" +msgstr "" + +#: forum/skins/default/templates/question.html:498 +msgid "Related questions" +msgstr "" + +#: forum/skins/default/templates/question_counter_widget.html:6 +msgid "Please decide if you like this question or not by voting" +msgstr "" + +#: forum/skins/default/templates/question_counter_widget.html:12 +msgid "" +"\n" +" vote\n" +" " +msgid_plural "" +"\n" +" votes\n" +" " +msgstr[0] "" +"\n" +"golos" +msgstr[1] "" +"\n" +"golosa" +msgstr[2] "" +"\n" +"golosov" + +#: forum/skins/default/templates/question_counter_widget.html:27 +msgid "" +"\n" +" answer \n" +" " +msgid_plural "" +"\n" +" answers \n" +" " +msgstr[0] "" +msgstr[1] "" + +#: forum/skins/default/templates/question_counter_widget.html:39 +msgid "" +"\n" +" view\n" +" " +msgid_plural "" +"\n" +" views\n" +" " +msgstr[0] "" +msgstr[1] "" + +#: forum/skins/default/templates/question_edit.html:5 +#: forum/skins/default/templates/question_edit.html:66 +msgid "Edit question" +msgstr "" + +#: forum/skins/default/templates/question_edit_tips.html:4 +msgid "question tips" +msgstr "" + +#: forum/skins/default/templates/question_edit_tips.html:7 +msgid "please ask a relevant question" +msgstr "" + +#: forum/skins/default/templates/question_edit_tips.html:10 +msgid "please try provide enough details" +msgstr "" + +#: forum/skins/default/templates/question_retag.html:4 +#: forum/skins/default/templates/question_retag.html:53 +msgid "Change tags" +msgstr "" + +#: forum/skins/default/templates/question_retag.html:40 +msgid "up to 5 tags, less than 20 characters each" +msgstr "" + +#: forum/skins/default/templates/question_retag.html:83 +msgid "Why use and modify tags?" +msgstr "" + +#: forum/skins/default/templates/question_retag.html:86 +msgid "tags help us keep Questions organized" +msgstr "" + +#: forum/skins/default/templates/question_retag.html:94 +msgid "tag editors receive special awards from the community" +msgstr "" + +#: forum/skins/default/templates/questions.html:32 +msgid "Found by tags" +msgstr "" + +#: forum/skins/default/templates/questions.html:36 +msgid "Search results" +msgstr "" + +#: forum/skins/default/templates/questions.html:38 +msgid "Found by title" +msgstr "" + +#: forum/skins/default/templates/questions.html:42 +msgid "Unanswered questions" +msgstr "" + +#: forum/skins/default/templates/questions.html:44 +msgid "All questions" +msgstr "" + +#: forum/skins/default/templates/questions.html:51 +msgid "In:" +msgstr "" + +#: forum/skins/default/templates/questions.html:53 +msgid "see unanswered questions" +msgstr "" + +#: forum/skins/default/templates/questions.html:55 +msgid "see your favorite questions" +msgstr "" + +#: forum/skins/default/templates/questions.html:59 +msgid "Sort by:" +msgstr "" + +#: forum/skins/default/templates/questions.html:64 +#: forum/skins/default/templates/questions.html:75 +msgid "click to see the newest questions" +msgstr "" + +#: forum/skins/default/templates/questions.html:70 +msgid "click to see the oldest questions" +msgstr "" + +#: forum/skins/default/templates/questions.html:83 +#: forum/skins/default/templates/questions.html:94 +msgid "click to see the most recently updated questions" +msgstr "" + +#: forum/skins/default/templates/questions.html:89 +msgid "click to see the least recently updated questions" +msgstr "" + +#: forum/skins/default/templates/questions.html:102 +#: forum/skins/default/templates/questions.html:113 +msgid "click to see hottest questions" +msgstr "" + +#: forum/skins/default/templates/questions.html:102 +msgid "less answers" +msgstr "" + +#: forum/skins/default/templates/questions.html:108 +msgid "click to see coldest questions" +msgstr "" + +#: forum/skins/default/templates/questions.html:108 +#: forum/skins/default/templates/questions.html:113 +msgid "more answers" +msgstr "" + +#: forum/skins/default/templates/questions.html:121 +#: forum/skins/default/templates/questions.html:132 +msgid "click to see most voted questions" +msgstr "" + +#: forum/skins/default/templates/questions.html:121 +msgid "unpopular" +msgstr "" + +#: forum/skins/default/templates/questions.html:127 +msgid "click to see least voted questions" +msgstr "" + +#: forum/skins/default/templates/questions.html:127 +#: forum/skins/default/templates/questions.html:132 +msgid "popular" +msgstr "" + +#: forum/skins/default/templates/questions.html:141 +#, python-format +msgid " One question found" +msgid_plural "%(q_num)s questions found" +msgstr[0] "" +msgstr[1] "" +msgstr[2] "" + +#: forum/skins/default/templates/questions.html:143 +#, python-format +msgid " %(q_num)s question" +msgid_plural "%(q_num)s questions" +msgstr[0] "" +msgstr[1] "" +msgstr[2] "" + +#: forum/skins/default/templates/questions.html:147 +#, python-format +msgid "with %(author_name)s's contributions" +msgstr "" + +#: forum/skins/default/templates/questions.html:151 +msgid "tagged" +msgstr "" + +#: forum/skins/default/templates/questions.html:157 +msgid "Search tips:" +msgstr "" + +#: forum/skins/default/templates/questions.html:161 +msgid "reset author" +msgstr "" + +#: forum/skins/default/templates/questions.html:165 +msgid "reset tags" +msgstr "" + +#: forum/skins/default/templates/questions.html:169 +#: forum/skins/default/templates/questions.html:173 +msgid "start over" +msgstr "" + +#: forum/skins/default/templates/questions.html:175 +msgid " - to expand, or dig in by adding more tags and revising the query." +msgstr "" + +#: forum/skins/default/templates/questions.html:178 +msgid "Search tip:" +msgstr "" + +#: forum/skins/default/templates/questions.html:178 +msgid "add tags and a query to focus your search" +msgstr "" + +#: forum/skins/default/templates/questions.html:190 +msgid "There are no unanswered questions here" +msgstr "" + +#: forum/skins/default/templates/questions.html:193 +msgid "No favorite questions here. " +msgstr "" + +#: forum/skins/default/templates/questions.html:194 +msgid "Please start (bookmark) some questions when you visit them" +msgstr "" + +#: forum/skins/default/templates/questions.html:199 +msgid "You can expand your search by " +msgstr "" + +#: forum/skins/default/templates/questions.html:203 +msgid "resetting author" +msgstr "" + +#: forum/skins/default/templates/questions.html:207 +msgid "resetting tags" +msgstr "" + +#: forum/skins/default/templates/questions.html:211 +#: forum/skins/default/templates/questions.html:215 +msgid "starting over" +msgstr "" + +#: forum/skins/default/templates/questions.html:220 +msgid "Please always feel free to ask your question!" +msgstr "" + +#: forum/skins/default/templates/questions.html:224 +msgid "Did not find what you were looking for?" +msgstr "" + +#: forum/skins/default/templates/questions.html:225 +msgid "Please, post your question!" +msgstr "" + +#: forum/skins/default/templates/questions.html:243 +msgid "Related tags" +msgstr "" + +#: forum/skins/default/templates/reopen.html:6 +#: forum/skins/default/templates/reopen.html:16 +msgid "Reopen question" +msgstr "" + +#: forum/skins/default/templates/reopen.html:19 +msgid "Open the previously closed question" +msgstr "" + +#: forum/skins/default/templates/reopen.html:22 +msgid "The question was closed for the following reason " +msgstr "" + +#: forum/skins/default/templates/reopen.html:22 +msgid "reason - leave blank in english" +msgstr "" + +#: forum/skins/default/templates/reopen.html:22 +msgid "on " +msgstr "" + +#: forum/skins/default/templates/reopen.html:22 +msgid "date closed" +msgstr "" + +#: forum/skins/default/templates/reopen.html:29 +msgid "Reopen this question" +msgstr "" + +#: forum/skins/default/templates/revisions_answer.html:7 +#: forum/skins/default/templates/revisions_answer.html:38 +#: forum/skins/default/templates/revisions_question.html:8 +#: forum/skins/default/templates/revisions_question.html:38 +msgid "Revision history" +msgstr "" + +#: forum/skins/default/templates/revisions_answer.html:50 +#: forum/skins/default/templates/revisions_question.html:50 +msgid "click to hide/show revision" +msgstr "" + +#: forum/skins/default/templates/tag_selector.html:5 +msgid "Interesting tags" +msgstr "" + +#: forum/skins/default/templates/tag_selector.html:15 +#, python-format +msgid "remove '%(tag_name)s' from the list of interesting tags" +msgstr "" + +#: forum/skins/default/templates/tag_selector.html:21 +#: forum/skins/default/templates/tag_selector.html:38 +msgid "Add" +msgstr "" + +#: forum/skins/default/templates/tag_selector.html:22 +msgid "Ignored tags" +msgstr "" + +#: forum/skins/default/templates/tag_selector.html:32 +#, python-format +msgid "remove '%(tag_name)s' from the list of ignored tags" +msgstr "" + +#: forum/skins/default/templates/tag_selector.html:41 +msgid "keep ignored questions hidden" +msgstr "" + +#: forum/skins/default/templates/tags.html:6 +#: forum/skins/default/templates/tags.html:30 +msgid "Tag list" +msgstr "" + +#: forum/skins/default/templates/tags.html:32 +msgid "sorted alphabetically" +msgstr "" + +#: forum/skins/default/templates/tags.html:32 +msgid "by name" +msgstr "" + +#: forum/skins/default/templates/tags.html:33 +msgid "sorted by frequency of tag use" +msgstr "" + +#: forum/skins/default/templates/tags.html:33 +msgid "by popularity" +msgstr "" + +#: forum/skins/default/templates/tags.html:39 +#, python-format +msgid "" +"All tags matching '<span class=\"darkred\"><strong>%(stag)s</strong></span>'" +msgstr "" + +#: forum/skins/default/templates/tags.html:42 +msgid "Nothing found" +msgstr "" + +#: forum/skins/default/templates/user_edit.html:6 +msgid "Edit user profile" +msgstr "" + +#: forum/skins/default/templates/user_edit.html:19 +msgid "edit profile" +msgstr "" + +#: forum/skins/default/templates/user_edit.html:33 +#: forum/skins/default/templates/user_info.html:53 +msgid "Registered user" +msgstr "" + +#: forum/skins/default/templates/user_edit.html:40 +msgid "Screen Name" +msgstr "" + +#: forum/skins/default/templates/user_edit.html:83 +#: forum/skins/default/templates/user_email_subscriptions.html:20 +msgid "Update" +msgstr "" + +#: forum/skins/default/templates/user_email_subscriptions.html:8 +msgid "Email subscription settings" +msgstr "" + +#: forum/skins/default/templates/user_email_subscriptions.html:9 +msgid "email subscription settings info" +msgstr "" + +#: forum/skins/default/templates/user_email_subscriptions.html:21 +msgid "Stop sending email" +msgstr "" + +#: forum/skins/default/templates/user_info.html:18 +msgid "change picture" +msgstr "" + +#: forum/skins/default/templates/user_info.html:25 +#: forum/skins/default/templates/users.html:26 forum/views/users.py:921 +msgid "reputation" +msgstr "" + +#: forum/skins/default/templates/user_info.html:35 +msgid "Moderate this user" +msgstr "" + +#: forum/skins/default/templates/user_info.html:47 +msgid "update profile" +msgstr "" + +#: forum/skins/default/templates/user_info.html:57 +msgid "real name" +msgstr "" + +#: forum/skins/default/templates/user_info.html:62 +msgid "member for" +msgstr "" + +#: forum/skins/default/templates/user_info.html:67 +msgid "last seen" +msgstr "" + +#: forum/skins/default/templates/user_info.html:73 +msgid "user website" +msgstr "" + +#: forum/skins/default/templates/user_info.html:79 +msgid "location" +msgstr "" + +#: forum/skins/default/templates/user_info.html:86 +msgid "age" +msgstr "" + +#: forum/skins/default/templates/user_info.html:87 +msgid "age unit" +msgstr "" + +#: forum/skins/default/templates/user_info.html:93 +msgid "todays unused votes" +msgstr "" + +#: forum/skins/default/templates/user_info.html:94 +msgid "votes left" +msgstr "" + +#: forum/skins/default/templates/user_reputation.html:29 +msgid "Your karma change log." +msgstr "" + +#: forum/skins/default/templates/user_reputation.html:31 +#, python-format +msgid "%(user_name)s's karma change log" +msgstr "" + +#: forum/skins/default/templates/user_stats.html:12 +#, python-format +msgid "" +"\n" +" <span class=\"count\">1</span> Question\n" +" " +msgid_plural "" +"\n" +" <span class=\"count\">%(counter)s</span> Questions\n" +" " +msgstr[0] "" +msgstr[1] "" + +#: forum/skins/default/templates/user_stats.html:23 +#, python-format +msgid "" +"\n" +" <span class=\"count\">1</span> Answer\n" +" " +msgid_plural "" +"\n" +" <span class=\"count\">%(counter)s</span> Answers\n" +" " +msgstr[0] "" +msgstr[1] "" + +#: forum/skins/default/templates/user_stats.html:36 +#, python-format +msgid "the answer has been voted for %(answer_score)s times" +msgstr "" + +#: forum/skins/default/templates/user_stats.html:36 +msgid "this answer has been selected as correct" +msgstr "" + +#: forum/skins/default/templates/user_stats.html:46 +#, python-format +msgid "" +"\n" +" (one comment)\n" +" " +msgid_plural "" +"\n" +" the answer has been commented %(comment_count)s times\n" +" " +msgstr[0] "" +msgstr[1] "" + +#: forum/skins/default/templates/user_stats.html:61 +#, python-format +msgid "" +"\n" +" <span class=\"count\">1</span> Vote\n" +" " +msgid_plural "" +"\n" +" <span class=\"count\">%(cnt)s</span> Votes\n" +" " +msgstr[0] "" +msgstr[1] "" + +#: forum/skins/default/templates/user_stats.html:72 +msgid "thumb up" +msgstr "" + +#: forum/skins/default/templates/user_stats.html:73 +msgid "user has voted up this many times" +msgstr "" + +#: forum/skins/default/templates/user_stats.html:77 +msgid "thumb down" +msgstr "" + +#: forum/skins/default/templates/user_stats.html:78 +msgid "user voted down this many times" +msgstr "" + +#: forum/skins/default/templates/user_stats.html:87 +#, python-format +msgid "" +"\n" +" <span class=\"count\">1</span> Tag\n" +" " +msgid_plural "" +"\n" +" <span class=\"count\">%(counter)s</span> Tags\n" +" " +msgstr[0] "" +msgstr[1] "" + +#: forum/skins/default/templates/user_stats.html:100 +#, python-format +msgid "" +"see other questions with %(view_user)s's contributions tagged '%(tag_name)s' " +msgstr "" + +#: forum/skins/default/templates/user_stats.html:115 +#, python-format +msgid "" +"\n" +" <span class=\"count\">1</span> Badge\n" +" " +msgid_plural "" +"\n" +" <span class=\"count\">%(counter)s</span> Badges\n" +" " +msgstr[0] "" +msgstr[1] "" + +#: forum/skins/default/templates/user_tabs.html:7 +msgid "User profile" +msgstr "" + +#: forum/skins/default/templates/user_tabs.html:7 forum/views/users.py:895 +msgid "overview" +msgstr "" + +#: forum/skins/default/templates/user_tabs.html:9 forum/views/users.py:903 +msgid "recent activity" +msgstr "" + +#: forum/skins/default/templates/user_tabs.html:12 forum/views/users.py:913 +msgid "comments and answers to others questions" +msgstr "" + +#: forum/skins/default/templates/user_tabs.html:13 forum/views/users.py:912 +msgid "responses" +msgstr "" + +#: forum/skins/default/templates/user_tabs.html:16 +msgid "graph of user reputation" +msgstr "" + +#: forum/skins/default/templates/user_tabs.html:17 +msgid "reputation history" +msgstr "" + +#: forum/skins/default/templates/user_tabs.html:20 forum/views/users.py:939 +msgid "user vote record" +msgstr "" + +#: forum/skins/default/templates/user_tabs.html:20 forum/views/users.py:938 +msgid "casted votes" +msgstr "" + +#: forum/skins/default/templates/user_tabs.html:23 +msgid "questions that user selected as his/her favorite" +msgstr "" + +#: forum/skins/default/templates/user_tabs.html:24 +msgid "favorites" +msgstr "" + +#: forum/skins/default/templates/user_tabs.html:27 forum/views/users.py:948 +msgid "email subscription settings" +msgstr "" + +#: forum/skins/default/templates/user_tabs.html:28 forum/views/users.py:947 +msgid "email subscriptions" +msgstr "" + +#: forum/skins/default/templates/users.html:6 +#: forum/skins/default/templates/users.html:24 +msgid "Users" +msgstr "" + +#: forum/skins/default/templates/users.html:27 +msgid "recent" +msgstr "" + +#: forum/skins/default/templates/users.html:29 +msgid "by username" +msgstr "" + +#: forum/skins/default/templates/users.html:35 +#, python-format +msgid "users matching query %(suser)s:" +msgstr "" + +#: forum/skins/default/templates/users.html:39 +msgid "Nothing found." +msgstr "" + +#: forum/skins/default/templates/users_questions.html:11 +msgid "this questions was selected as favorite" +msgstr "" + +#: forum/skins/default/templates/users_questions.html:12 +msgid "thumb-up on" +msgstr "" + +#: forum/skins/default/templates/users_questions.html:19 +msgid "thumb-up off" +msgstr "" + +#: forum/skins/default/templates/authopenid/changeemail.html:3 +#: forum/skins/default/templates/authopenid/changeemail.html:9 +#: forum/skins/default/templates/authopenid/changeemail.html:38 +msgid "Change email" +msgstr "" + +#: forum/skins/default/templates/authopenid/changeemail.html:11 +msgid "Save your email address" +msgstr "" + +#: forum/skins/default/templates/authopenid/changeemail.html:16 +#, python-format +msgid "change %(email)s info" +msgstr "" + +#: forum/skins/default/templates/authopenid/changeemail.html:18 +#, python-format +msgid "here is why email is required, see %(gravatar_faq_url)s" +msgstr "" + +#: forum/skins/default/templates/authopenid/changeemail.html:31 +msgid "Your new Email" +msgstr "" + +#: forum/skins/default/templates/authopenid/changeemail.html:31 +msgid "Your Email" +msgstr "" + +#: forum/skins/default/templates/authopenid/changeemail.html:38 +msgid "Save Email" +msgstr "" + +#: forum/skins/default/templates/authopenid/changeemail.html:49 +msgid "Validate email" +msgstr "" + +#: forum/skins/default/templates/authopenid/changeemail.html:52 +#, python-format +msgid "validate %(email)s info or go to %(change_email_url)s" +msgstr "" + +#: forum/skins/default/templates/authopenid/changeemail.html:57 +msgid "Email not changed" +msgstr "" + +#: forum/skins/default/templates/authopenid/changeemail.html:60 +#, python-format +msgid "old %(email)s kept, if you like go to %(change_email_url)s" +msgstr "" + +#: forum/skins/default/templates/authopenid/changeemail.html:65 +msgid "Email changed" +msgstr "" + +#: forum/skins/default/templates/authopenid/changeemail.html:68 +#, python-format +msgid "your current %(email)s can be used for this" +msgstr "" + +#: forum/skins/default/templates/authopenid/changeemail.html:73 +msgid "Email verified" +msgstr "" + +#: forum/skins/default/templates/authopenid/changeemail.html:76 +msgid "thanks for verifying email" +msgstr "" + +#: forum/skins/default/templates/authopenid/changeemail.html:81 +msgid "email key not sent" +msgstr "" + +#: forum/skins/default/templates/authopenid/changeemail.html:84 +#, python-format +msgid "email key not sent %(email)s change email here %(change_link)s" +msgstr "" + +#: forum/skins/default/templates/authopenid/changeopenid.html:8 +msgid "Account: change OpenID URL" +msgstr "" + +#: forum/skins/default/templates/authopenid/changeopenid.html:12 +msgid "" +"This is where you can change your OpenID URL. Make sure you remember it!" +msgstr "" + +#: forum/skins/default/templates/authopenid/changeopenid.html:14 +#: forum/skins/default/templates/authopenid/delete.html:14 +#: forum/skins/default/templates/authopenid/delete.html:24 +msgid "Please correct errors below:" +msgstr "" + +#: forum/skins/default/templates/authopenid/changeopenid.html:29 +msgid "OpenID URL:" +msgstr "" + +#: forum/skins/default/templates/authopenid/changepw.html:7 +msgid "Account: change password" +msgstr "" + +#: forum/skins/default/templates/authopenid/changepw.html:8 +msgid "This is where you can change your password. Make sure you remember it!" +msgstr "" + +#: forum/skins/default/templates/authopenid/complete.html:19 +msgid "Connect your OpenID with this site" +msgstr "" + +#: forum/skins/default/templates/authopenid/complete.html:22 +msgid "Connect your OpenID with your account on this site" +msgstr "" + +#: forum/skins/default/templates/authopenid/complete.html:27 +#, python-format +msgid "register new %(provider)s account info, see %(gravatar_faq_url)s" +msgstr "" + +#: forum/skins/default/templates/authopenid/complete.html:31 +#, python-format +msgid "" +"%(username)s already exists, choose another name for \n" +" %(provider)s. Email is required too, see %" +"(gravatar_faq_url)s\n" +" " +msgstr "" + +#: forum/skins/default/templates/authopenid/complete.html:35 +#, python-format +msgid "" +"register new external %(provider)s account info, see %(gravatar_faq_url)s" +msgstr "" + +#: forum/skins/default/templates/authopenid/complete.html:38 +#, python-format +msgid "register new Facebook connect account info, see %(gravatar_faq_url)s" +msgstr "" + +#: forum/skins/default/templates/authopenid/complete.html:42 +msgid "This account already exists, please use another." +msgstr "" + +#: forum/skins/default/templates/authopenid/complete.html:57 +msgid "Sorry, looks like we have some errors:" +msgstr "" + +#: forum/skins/default/templates/authopenid/complete.html:82 +msgid "Screen name label" +msgstr "" + +#: forum/skins/default/templates/authopenid/complete.html:89 +msgid "Email address label" +msgstr "" + +#: forum/skins/default/templates/authopenid/complete.html:95 +#: forum/skins/default/templates/authopenid/signup.html:18 +msgid "receive updates motivational blurb" +msgstr "" + +#: forum/skins/default/templates/authopenid/complete.html:99 +#: forum/skins/default/templates/authopenid/signup.html:22 +msgid "please select one of the options above" +msgstr "" + +#: forum/skins/default/templates/authopenid/complete.html:102 +msgid "Tag filter tool will be your right panel, once you log in." +msgstr "" + +#: forum/skins/default/templates/authopenid/complete.html:103 +msgid "create account" +msgstr "" + +#: forum/skins/default/templates/authopenid/complete.html:112 +msgid "Existing account" +msgstr "" + +#: forum/skins/default/templates/authopenid/complete.html:113 +msgid "user name" +msgstr "" + +#: forum/skins/default/templates/authopenid/complete.html:114 +msgid "password" +msgstr "" + +#: forum/skins/default/templates/authopenid/complete.html:121 +msgid "Register" +msgstr "" + +#: forum/skins/default/templates/authopenid/complete.html:122 +#: forum/skins/default/templates/authopenid/signin.html:168 +msgid "Forgot your password?" +msgstr "" + +#: forum/skins/default/templates/authopenid/confirm_email.txt:2 +msgid "Thank you for registering at our Q&A forum!" +msgstr "" + +#: forum/skins/default/templates/authopenid/confirm_email.txt:4 +msgid "Your account details are:" +msgstr "" + +#: forum/skins/default/templates/authopenid/confirm_email.txt:6 +msgid "Username:" +msgstr "" + +#: forum/skins/default/templates/authopenid/confirm_email.txt:7 +#: forum/skins/default/templates/authopenid/delete.html:19 +msgid "Password:" +msgstr "" + +#: forum/skins/default/templates/authopenid/confirm_email.txt:9 +msgid "Please sign in here:" +msgstr "" + +#: forum/skins/default/templates/authopenid/confirm_email.txt:12 +#: forum/skins/default/templates/authopenid/email_validation.txt:14 +#: forum/skins/default/templates/authopenid/sendpw_email.txt:8 +msgid "" +"Sincerely,\n" +"Forum Administrator" +msgstr "" + +#: forum/skins/default/templates/authopenid/delete.html:8 +msgid "Account: delete account" +msgstr "" + +#: forum/skins/default/templates/authopenid/delete.html:12 +msgid "" +"Note: After deleting your account, anyone will be able to register this " +"username." +msgstr "" + +#: forum/skins/default/templates/authopenid/delete.html:16 +msgid "Check confirm box, if you want delete your account." +msgstr "" + +#: forum/skins/default/templates/authopenid/delete.html:31 +msgid "I am sure I want to delete my account." +msgstr "" + +#: forum/skins/default/templates/authopenid/delete.html:32 +msgid "Password/OpenID URL" +msgstr "" + +#: forum/skins/default/templates/authopenid/delete.html:32 +msgid "(required for your security)" +msgstr "" + +#: forum/skins/default/templates/authopenid/delete.html:34 +msgid "Delete account permanently" +msgstr "" + +#: forum/skins/default/templates/authopenid/email_validation.txt:2 +msgid "Greetings from the Q&A forum" +msgstr "" + +#: forum/skins/default/templates/authopenid/email_validation.txt:4 +msgid "To make use of the Forum, please follow the link below:" +msgstr "" + +#: forum/skins/default/templates/authopenid/email_validation.txt:8 +msgid "Following the link above will help us verify your email address." +msgstr "" + +#: forum/skins/default/templates/authopenid/email_validation.txt:10 +msgid "" +"If you beleive that this message was sent in mistake - \n" +"no further action is needed. Just ingore this email, we apologize\n" +"for any inconvenience" +msgstr "" + +#: forum/skins/default/templates/authopenid/external_legacy_login_info.html:4 +#: forum/skins/default/templates/authopenid/external_legacy_login_info.html:7 +msgid "Traditional login information" +msgstr "" + +#: forum/skins/default/templates/authopenid/external_legacy_login_info.html:12 +#, python-format +msgid "" +"how to login with password through external login website or use %" +"(feedback_url)s" +msgstr "" + +#: forum/skins/default/templates/authopenid/sendpw.html:4 +#: forum/skins/default/templates/authopenid/sendpw.html:7 +msgid "Send new password" +msgstr "" + +#: forum/skins/default/templates/authopenid/sendpw.html:10 +msgid "password recovery information" +msgstr "" + +#: forum/skins/default/templates/authopenid/sendpw.html:21 +msgid "Reset password" +msgstr "" + +#: forum/skins/default/templates/authopenid/sendpw.html:22 +msgid "return to login" +msgstr "" + +#: forum/skins/default/templates/authopenid/sendpw_email.txt:2 +#, python-format +msgid "" +"Someone has requested to reset your password on %(site_url)s.\n" +"If it were not you, it is safe to ignore this email." +msgstr "" + +#: forum/skins/default/templates/authopenid/sendpw_email.txt:5 +#, python-format +msgid "" +"email explanation how to use new %(password)s for %(username)s\n" +"with the %(key_link)s" +msgstr "" + +#: forum/skins/default/templates/authopenid/signin.html:5 +#: forum/skins/default/templates/authopenid/signin.html:21 +msgid "User login" +msgstr "" + +#: forum/skins/default/templates/authopenid/signin.html:28 +#, python-format +msgid "" +"\n" +" Your answer to %(title)s %(summary)s will be posted once you " +"log in\n" +" " +msgstr "" + +#: forum/skins/default/templates/authopenid/signin.html:35 +#, python-format +msgid "" +"Your question \n" +" %(title)s %(summary)s will be posted once you log in\n" +" " +msgstr "" + +#: forum/skins/default/templates/authopenid/signin.html:42 +msgid "Click to sign in through any of these services." +msgstr "" + +#: forum/skins/default/templates/authopenid/signin.html:144 +msgid "Enter your <span id=\"enter_your_what\">Provider user name</span>" +msgstr "" + +#: forum/skins/default/templates/authopenid/signin.html:151 +msgid "" +"Enter your <a class=\"openid_logo\" href=\"http://openid.net\">OpenID</a> " +"web address" +msgstr "" + +#: forum/skins/default/templates/authopenid/signin.html:153 +#: forum/skins/default/templates/authopenid/signin.html:166 +msgid "Login" +msgstr "" + +#: forum/skins/default/templates/authopenid/signin.html:157 +msgid "Enter your login name and password" +msgstr "" + +#: forum/skins/default/templates/authopenid/signin.html:161 +msgid "Login name" +msgstr "" + +#: forum/skins/default/templates/authopenid/signin.html:163 +msgid "Password" +msgstr "" + +#: forum/skins/default/templates/authopenid/signin.html:167 +msgid "Create account" +msgstr "" + +#: forum/skins/default/templates/authopenid/signin.html:178 +msgid "Why use OpenID?" +msgstr "" + +#: forum/skins/default/templates/authopenid/signin.html:181 +msgid "with openid it is easier" +msgstr "" + +#: forum/skins/default/templates/authopenid/signin.html:184 +msgid "reuse openid" +msgstr "" + +#: forum/skins/default/templates/authopenid/signin.html:187 +msgid "openid is widely adopted" +msgstr "" + +#: forum/skins/default/templates/authopenid/signin.html:190 +msgid "openid is supported open standard" +msgstr "" + +#: forum/skins/default/templates/authopenid/signin.html:195 +msgid "Find out more" +msgstr "" + +#: forum/skins/default/templates/authopenid/signin.html:196 +msgid "Get OpenID" +msgstr "" + +#: forum/skins/default/templates/authopenid/signup.html:4 +msgid "Signup" +msgstr "" + +#: forum/skins/default/templates/authopenid/signup.html:8 +msgid "Create login name and password" +msgstr "" + +#: forum/skins/default/templates/authopenid/signup.html:10 +msgid "Traditional signup info" +msgstr "" + +#: forum/skins/default/templates/authopenid/signup.html:25 +msgid "" +"Please read and type in the two words below to help us prevent automated " +"account creation." +msgstr "" + +#: forum/skins/default/templates/authopenid/signup.html:27 +msgid "Create Account" +msgstr "" + +#: forum/skins/default/templates/authopenid/signup.html:29 +msgid "return to OpenID login" +msgstr "" + +#: forum/skins/default/templates/fbconnect/xd_receiver.html:5 +#, python-format +msgid "Connect to %(APP_SHORT_NAME)s with Facebook!" +msgstr "" + +#: forum/templatetags/extra_tags.py:175 forum/templatetags/extra_tags.py:202 +msgid "reputation points" +msgstr "" + +#: forum/templatetags/extra_tags.py:262 +msgid "2 days ago" +msgstr "" + +#: forum/templatetags/extra_tags.py:264 +msgid "yesterday" +msgstr "" + +#: forum/templatetags/extra_tags.py:266 +#, python-format +msgid "%(hr)d hour ago" +msgid_plural "%(hr)d hours ago" +msgstr[0] "" +msgstr[1] "" + +#: forum/templatetags/extra_tags.py:268 +#, python-format +msgid "%(min)d min ago" +msgid_plural "%(min)d mins ago" +msgstr[0] "" +msgstr[1] "" + +#: forum/utils/forms.py:30 +msgid "this field is required" +msgstr "" + +#: forum/utils/forms.py:45 +msgid "choose a username" +msgstr "" + +#: forum/utils/forms.py:50 +msgid "user name is required" +msgstr "" + +#: forum/utils/forms.py:51 +msgid "sorry, this name is taken, please choose another" +msgstr "" + +#: forum/utils/forms.py:52 +msgid "sorry, this name is not allowed, please choose another" +msgstr "" + +#: forum/utils/forms.py:53 +msgid "sorry, there is no user with this name" +msgstr "" + +#: forum/utils/forms.py:54 +msgid "sorry, we have a serious error - user name is taken by several users" +msgstr "" + +#: forum/utils/forms.py:55 +msgid "user name can only consist of letters, empty space and underscore" +msgstr "" + +#: forum/utils/forms.py:109 +msgid "your email address" +msgstr "" + +#: forum/utils/forms.py:110 +msgid "email address is required" +msgstr "" + +#: forum/utils/forms.py:112 +msgid "this email is already used by someone else, please choose another" +msgstr "" + +#: forum/utils/forms.py:140 +msgid "choose password" +msgstr "" + +#: forum/utils/forms.py:141 +msgid "password is required" +msgstr "" + +#: forum/utils/forms.py:144 +msgid "retype password" +msgstr "" + +#: forum/utils/forms.py:145 +msgid "please, retype your password" +msgstr "" + +#: forum/utils/forms.py:146 +msgid "sorry, entered passwords did not match, please try again" +msgstr "" + +#: forum/views/auth.py:104 forum/views/auth.py:113 +msgid "" +"Sorry, these login credentials belong to anoother user. Plese terminate your " +"current session and try again." +msgstr "" + +#: forum/views/auth.py:106 +msgid "You are already logged in with that user." +msgstr "" + +#: forum/views/auth.py:111 +msgid "These login credentials are already associated with your account." +msgstr "" + +#: forum/views/auth.py:117 +msgid "The new credentials are now associated with your account" +msgstr "" + +#: forum/views/auth.py:155 +msgid "" +"Oops, something went wrong in the middle of this process. Please try again." +msgstr "" + +#: forum/views/auth.py:215 +msgid "Temporary login link" +msgstr "" + +#: forum/views/auth.py:220 +msgid "An email has been sent with your temporary login key" +msgstr "" + +#: forum/views/auth.py:235 +msgid "" +"You are logged in with a temporary access key, please take the time to fix " +"your issue with authentication." +msgstr "" + +#: forum/views/auth.py:241 +msgid "Email Validation" +msgstr "" + +#: forum/views/auth.py:252 +msgid "Thank you, your email is now validated." +msgstr "" + +#: forum/views/auth.py:276 +msgid "Your password was changed" +msgstr "" + +#: forum/views/auth.py:278 +msgid "New password set" +msgstr "" + +#: forum/views/auth.py:311 +#, python-format +msgid "You removed the association with %s" +msgstr "" + +#: forum/views/auth.py:350 +#, python-format +msgid "Welcome back %s, you are now logged in" +msgstr "" + +#: forum/views/commands.py:209 +#, python-format +msgid "subscription saved, %(email)s needs validation, see %(details_url)s" +msgstr "" + +#: forum/views/commands.py:217 +msgid "email update frequency has been set to daily" +msgstr "" + +#: forum/views/meta.py:34 +msgid "Q&A forum feedback" +msgstr "" + +#: forum/views/meta.py:35 +msgid "Thanks for the feedback!" +msgstr "" + +#: forum/views/meta.py:43 +msgid "We look forward to hearing your feedback! Please, give it next time :)" +msgstr "" + +#: forum/views/users.py:856 forum/views/users.py:860 +msgid "changes saved" +msgstr "" + +#: forum/views/users.py:866 +msgid "email updates canceled" +msgstr "" + +#: forum/views/users.py:896 +msgid "user profile" +msgstr "" + +#: forum/views/users.py:897 +msgid "user profile overview" +msgstr "" + +#: forum/views/users.py:904 +msgid "recent user activity" +msgstr "" + +#: forum/views/users.py:905 +msgid "profile - recent activity" +msgstr "" + +#: forum/views/users.py:914 +msgid "profile - responses" +msgstr "" + +#: forum/views/users.py:922 +msgid "user reputation in the community" +msgstr "" + +#: forum/views/users.py:923 +msgid "profile - user reputation" +msgstr "" + +#: forum/views/users.py:929 +msgid "favorite questions" +msgstr "" + +#: forum/views/users.py:930 +msgid "users favorite questions" +msgstr "" + +#: forum/views/users.py:931 +msgid "profile - favorite questions" +msgstr "" + +#: forum/views/users.py:940 +msgid "profile - votes" +msgstr "" + +#: forum/views/users.py:949 +msgid "profile - email subscriptions" +msgstr "" + +#: forum/views/writers.py:70 +msgid "uploading images is limited to users with >60 reputation points" +msgstr "" + +#: forum/views/writers.py:72 +msgid "allowed file types are 'jpg', 'jpeg', 'gif', 'bmp', 'png', 'tiff'" +msgstr "" + +#: forum/views/writers.py:74 +#, python-format +msgid "maximum upload file size is %sK" +msgstr "" + +#: forum/views/writers.py:76 +#, python-format +msgid "" +"Error uploading file. Please contact the site administrator. Thank you. %s" +msgstr "" + +#: forum_modules/books/urls.py:7 forum_modules/books/urls.py:8 +#: forum_modules/books/urls.py:9 +msgid "books/" +msgstr "" + +#: stackexchange/management/commands/load_stackexchange.py:124 +msgid "Congratulations, you are now an Administrator" +msgstr "" diff --git a/settings.py b/settings.py index 65aa0d41..f9b776cd 100644 --- a/settings.py +++ b/settings.py @@ -31,6 +31,7 @@ MIDDLEWARE_CLASSES = ( #'recaptcha_django.middleware.ReCaptchaMiddleware', 'django.middleware.transaction.TransactionMiddleware', 'debug_toolbar.middleware.DebugToolbarMiddleware', + 'forum.middleware.view_log.ViewLogMiddleware', ) TEMPLATE_CONTEXT_PROCESSORS = ( @@ -73,7 +74,8 @@ INSTALLED_APPS = ( 'forum', 'django_authopenid', 'debug_toolbar' , - #'stackexchange', #se loader + #'forum.importers.stackexchange', #se loader + 'south', ) AUTHENTICATION_BACKENDS = ('django.contrib.auth.backends.ModelBackend',) |