From 9c34f4130b843480ab34b463f40ea6d4f9bfbd4c Mon Sep 17 00:00:00 2001 From: Evgeny Fadeev Date: Thu, 27 Jan 2011 19:06:47 -0500 Subject: fixed a bug in the template faq as reported by Benoit, sub-version 64 --- askbot/__init__.py | 2 +- askbot/skins/default/templates/faq.html | 2 +- askbot/tests/page_load_tests.py | 5 +++++ 3 files changed, 7 insertions(+), 2 deletions(-) diff --git a/askbot/__init__.py b/askbot/__init__.py index 95b32800..c280de96 100644 --- a/askbot/__init__.py +++ b/askbot/__init__.py @@ -19,4 +19,4 @@ def get_version(): """returns version of the askbot app this version is meaningful for pypi only """ - return '0.6.63' + return '0.6.64' diff --git a/askbot/skins/default/templates/faq.html b/askbot/skins/default/templates/faq.html index ed31c50b..74d5b0ef 100644 --- a/askbot/skins/default/templates/faq.html +++ b/askbot/skins/default/templates/faq.html @@ -4,7 +4,7 @@ {% block content %}

{% trans %}Frequently Asked Questions {% endtrans %}({% trans %}FAQ{% endtrans %})

{% trans %}What kinds of questions can I ask here?{% endtrans %}

-

Most importanly - questions should be relevant to this community.{% endtrans %} +

{% trans %}Most importanly - questions should be relevant to this community.{% endtrans %} {% trans %}Before asking the question - please make sure to use search to see whether your question has alredy been answered.{% endtrans %}

{% trans %}What questions should I avoid asking?{% endtrans %}

diff --git a/askbot/tests/page_load_tests.py b/askbot/tests/page_load_tests.py index a4ef2547..7d9fdc26 100644 --- a/askbot/tests/page_load_tests.py +++ b/askbot/tests/page_load_tests.py @@ -236,6 +236,11 @@ class PageLoadTests(PageLoadTestCase): status_code=200, follow=True, ) + self.try_url( + 'faq', + template='faq.html', + status_code=200, + ) def test_non_user_urls(self): self.proto_test_non_user_urls() -- cgit v1.2.3-1-g7c22 From d0ca2ba84f869f5f18baa09ee6600d54f7793ddc Mon Sep 17 00:00:00 2001 From: Evgeny Fadeev Date: Thu, 27 Jan 2011 19:32:33 -0500 Subject: removed usage of listA selector in live_search.js --- askbot/__init__.py | 2 +- askbot/skins/default/media/js/live_search.js | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/askbot/__init__.py b/askbot/__init__.py index c280de96..7c2290ee 100644 --- a/askbot/__init__.py +++ b/askbot/__init__.py @@ -19,4 +19,4 @@ def get_version(): """returns version of the askbot app this version is meaningful for pypi only """ - return '0.6.64' + return '0.6.65' diff --git a/askbot/skins/default/media/js/live_search.js b/askbot/skins/default/media/js/live_search.js index 965002f9..57621cd1 100644 --- a/askbot/skins/default/media/js/live_search.js +++ b/askbot/skins/default/media/js/live_search.js @@ -3,7 +3,7 @@ $(document).ready(function(){ var query = $('input#keywords'); var prev_text = $.trim(query.val()); var running = false; - var q_list_sel = 'listA';//id of question listing div + var q_list_sel = 'question-list';//id of question listing div var refresh_x_button = function(){ if ($.trim(query.val()).length > 0){ -- cgit v1.2.3-1-g7c22 From 0a3f420f0b2168216dddff2bf47e1c8464ec7651 Mon Sep 17 00:00:00 2001 From: Evgeny Fadeev Date: Fri, 28 Jan 2011 18:52:57 -0500 Subject: fixed an orm query --- askbot/models/question.py | 8 +++++--- 1 file changed, 5 insertions(+), 3 deletions(-) diff --git a/askbot/models/question.py b/askbot/models/question.py index 0f4a0027..03274a7f 100644 --- a/askbot/models/question.py +++ b/askbot/models/question.py @@ -114,12 +114,14 @@ class QuestionManager(models.Manager): | models.Q(answers__text__search = search_query) ) elif settings.DATABASE_ENGINE == 'postgresql_psycopg2': - rank_clause = "ts_rank(question.text_search_vector, to_tsquery('%s'))"; + rank_clause = "ts_rank(question.text_search_vector, to_tsquery(%s))"; search_query = '&'.join(search_query.split()) + extra_params = ("'" + search_query + "'",) extra_kwargs = { - 'select': {'relevance': rank_clause % search_query}, + 'select': {'relevance': rank_clause}, 'where': ['text_search_vector @@ to_tsquery(%s)'], - 'params': ["'" + search_query + "'"] + 'params': extra_params, + 'select_params': extra_params, } if askbot.conf.should_show_sort_by_relevance(): if sort_method == 'relevance-desc': -- cgit v1.2.3-1-g7c22 From 507f6d32c6eec7114cf05e0ff9f5009aa9b0143d Mon Sep 17 00:00:00 2001 From: Evgeny Fadeev Date: Fri, 28 Jan 2011 23:20:01 -0500 Subject: added a management command fix_question_tags --- askbot/__init__.py | 2 +- askbot/doc/source/management-commands.rst | 6 +++ askbot/management/commands/delete_unused_tags.py | 8 +-- askbot/management/commands/fix_question_tags.py | 53 ++++++++++++++++++++ askbot/models/signals.py | 63 ++++++++++++++++++++++++ askbot/utils/console.py | 12 +++++ 6 files changed, 139 insertions(+), 5 deletions(-) create mode 100644 askbot/management/commands/fix_question_tags.py diff --git a/askbot/__init__.py b/askbot/__init__.py index 7c2290ee..b084cb5b 100644 --- a/askbot/__init__.py +++ b/askbot/__init__.py @@ -19,4 +19,4 @@ def get_version(): """returns version of the askbot app this version is meaningful for pypi only """ - return '0.6.65' + return '0.6.66' diff --git a/askbot/doc/source/management-commands.rst b/askbot/doc/source/management-commands.rst index 42458f8d..34c47155 100644 --- a/askbot/doc/source/management-commands.rst +++ b/askbot/doc/source/management-commands.rst @@ -114,6 +114,12 @@ The commands from this section will help fix those issues. +--------------------------------+-------------------------------------------------------------+ | `fix_revisionless_posts` | adds a revision record to posts that lack them | +--------------------------------+-------------------------------------------------------------+ +| `fix_question_tags` | takes tag names from the record on the question table | +| | and stores them in the tag table. This defect may show when | +| | the server process is interrupted after the question was | +| | saved, but tags were not updated, and the symptom is that | +| | the question cannot be found via the tag search. | ++--------------------------------+-------------------------------------------------------------+ The above commands are safe to run at any time, also they do not require additional parameters. In the future all these will be replaced with just one simple command. diff --git a/askbot/management/commands/delete_unused_tags.py b/askbot/management/commands/delete_unused_tags.py index e5e340d0..acb28fa7 100644 --- a/askbot/management/commands/delete_unused_tags.py +++ b/askbot/management/commands/delete_unused_tags.py @@ -1,6 +1,7 @@ from django.core.management.base import NoArgsCommand from django.db import transaction from askbot import models +from askbot.utils import console import sys class Command(NoArgsCommand): @@ -17,10 +18,9 @@ class Command(NoArgsCommand): tag.delete() transaction.commit() count += 1 - sys.stdout.write('%6.2f%%' % (100*float(count)/float(total))) - sys.stdout.flush() - sys.stdout.write('\b'*7) - sys.stdout.write('\n') + progress = 100*float(count)/float(total) + console.print_progress('%6.2f%%', progress) + print '%6.2f%%' % 100 if deleted_tags: found_count = len(deleted_tags) diff --git a/askbot/management/commands/fix_question_tags.py b/askbot/management/commands/fix_question_tags.py new file mode 100644 index 00000000..1d5cae7e --- /dev/null +++ b/askbot/management/commands/fix_question_tags.py @@ -0,0 +1,53 @@ +import sys +from django.core.management.base import NoArgsCommand +from django.db import transaction +from askbot import models +from askbot.utils import console +from askbot.models import signals + +FORMAT_STRING = '%6.2f%%' + +class Command(NoArgsCommand): + def handle_noargs(self, **options): + signal_data = signals.pop_all_db_signal_receivers() + self.run_command() + signals.set_all_db_signal_receivers(signal_data) + + @transaction.commit_manually + def run_command(self): + """method that runs the actual command""" + + questions = models.Question.objects.all() + checked_count = 0 + found_count = 0 + total_count = questions.count() + print "Searching for questions with incomplete tag records:", + for question in questions: + + tags = question.tags.all() + denorm_tag_set = set(question.get_tag_names()) + norm_tag_set = set(question.tags.values_list('name', flat=True)) + if norm_tag_set != denorm_tag_set: + + if question.last_edited_by: + user = question.last_edited_by + timestamp = question.last_edited_at + else: + user = question.author + timestamp = question.added_at + + question.update_tags( + tagnames = question.tagnames, + user = user, + timestamp = timestamp + ) + found_count += 1 + transaction.commit() + checked_count += 1 + progress = 100*float(checked_count)/float(total_count) + console.print_progress(FORMAT_STRING, progress) + print FORMAT_STRING % 100 + if found_count: + print '%d problem questions found, tag records restored' % found_count + else: + print 'Nothing found' diff --git a/askbot/models/signals.py b/askbot/models/signals.py index 83ea6eda..d28cd4a5 100644 --- a/askbot/models/signals.py +++ b/askbot/models/signals.py @@ -1,6 +1,11 @@ """Custom django signals defined for the askbot forum application. """ import django.dispatch +from django.db.models.signals import pre_save, post_save, pre_delete, post_delete, post_syncdb +try: + from django.db.models.signals import m2m_changed +except ImportError: + pass tags_updated = django.dispatch.Signal( providing_args=['tags', 'user', 'timestamp'] @@ -26,3 +31,61 @@ post_updated = django.dispatch.Signal( ] ) site_visited = django.dispatch.Signal(providing_args=['user', 'timestamp']) + +def pop_signal_receivers(signal): + """disables a given signal by removing listener functions + and returns the list + """ + receivers = signal.receivers + signal.receivers = list() + return receivers + +def set_signal_receivers(signal, receiver_list): + """assigns a value of the receiver_list + to the signal receivers + """ + signal.receivers = receiver_list + +def pop_all_db_signal_receivers(): + """loops through all relevant signals + pops their receivers and returns a + dictionary where signals are keys + and lists of receivers are values + """ + #this is the only askbot signal that is not defined here + #must use this to avoid a circular import + from askbot.models.badges import award_badges_signal + signals = ( + #askbot signals + tags_updated, + edit_question_or_answer, + delete_question_or_answer, + flag_offensive, + user_updated, + user_logged_in, + post_updated, + award_badges_signal, + #django signals + pre_save, + post_save, + pre_delete, + post_delete, + post_syncdb, + ) + if 'm2m_changed' in globals(): + signals += m2m_changed + + receiver_data = dict() + for signal in signals: + receiver_data[signal] = pop_signal_receivers(signal) + + return receiver_data + +def set_all_db_signal_receivers(receiver_data): + """takes receiver data as an argument + where the argument is as returned by the + pop_all_db_signal_receivers() call + and sets the receivers back to the signals + """ + for (signal, receivers) in receiver_data.items(): + signal.receivers = receivers diff --git a/askbot/utils/console.py b/askbot/utils/console.py index b11a8b4e..041fc839 100644 --- a/askbot/utils/console.py +++ b/askbot/utils/console.py @@ -1,5 +1,6 @@ """functions that directly handle user input """ +import sys import time from askbot.utils import path @@ -47,3 +48,14 @@ def open_new_file(prompt_phrase, extension = '', hint = None): file_object = path.create_file_if_does_not_exist(file_path, print_warning = True) return file_object + +def print_progress(format_string, progress): + """print dynamic output of progress of some + operation to the console and clear the output with + a backspace character to have the number increment + in-place""" + output = format_string % progress + sys.stdout.write(output) + sys.stdout.flush() + sys.stdout.write('\b' * len(output)) + -- cgit v1.2.3-1-g7c22 From ec15fc285f62f713e4ee3f16c489757d04e8a94d Mon Sep 17 00:00:00 2001 From: Evgeny Fadeev Date: Sun, 30 Jan 2011 18:18:19 -0500 Subject: it is now possible to either force lower-casing tags or allow freehand character case without a possibility to have duplicate tag names, and fixed the fix_question_tags management command --- askbot/__init__.py | 2 +- askbot/conf/forum_data_rules.py | 15 +++++++++++ askbot/forms.py | 27 ++++++++++++++++--- askbot/management/commands/fix_question_tags.py | 33 ++++++++++++++++++++--- askbot/skins/default/media/js/post.js | 2 +- askbot/tests/__init__.py | 1 + askbot/tests/form_tests.py | 35 +++++++++++++++++++++++++ askbot/views/writers.py | 5 +++- 8 files changed, 109 insertions(+), 11 deletions(-) create mode 100644 askbot/tests/form_tests.py diff --git a/askbot/__init__.py b/askbot/__init__.py index b084cb5b..4b161e23 100644 --- a/askbot/__init__.py +++ b/askbot/__init__.py @@ -19,4 +19,4 @@ def get_version(): """returns version of the askbot app this version is meaningful for pypi only """ - return '0.6.66' + return '0.6.67' diff --git a/askbot/conf/forum_data_rules.py b/askbot/conf/forum_data_rules.py index 972beff8..4ce3a239 100644 --- a/askbot/conf/forum_data_rules.py +++ b/askbot/conf/forum_data_rules.py @@ -29,6 +29,21 @@ settings.register( ) ) +settings.register( + livesettings.BooleanValue( + FORUM_DATA_RULES, + 'FORCE_LOWERCASE_TAGS', + default = False, + description = _('Force lowercase the tags'), + help_text = _( + 'Attention: after checking this, please back up the database, ' + 'and run a management command: ' + 'python manage.py fix_question_tags to globally ' + 'rename the tags' + ) + ) +) + settings.register( livesettings.IntegerValue( FORUM_DATA_RULES, diff --git a/askbot/forms.py b/askbot/forms.py index fb9dcc73..ccb65ab5 100644 --- a/askbot/forms.py +++ b/askbot/forms.py @@ -94,7 +94,7 @@ class TagNamesField(forms.CharField): split_re = re.compile(const.TAG_SPLIT_REGEX) tag_strings = split_re.split(data) - out_tag_list = [] + entered_tags = [] tag_count = len(tag_strings) if tag_count > askbot_settings.MAX_TAGS_PER_POST: max_tags = askbot_settings.MAX_TAGS_PER_POST @@ -118,9 +118,28 @@ class TagNamesField(forms.CharField): 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) + if tag not in entered_tags: + entered_tags.append(tag) + + #normalize character case of tags + if askbot_settings.FORCE_LOWERCASE_TAGS: + entered_tags = set([name.lower() for name in entered_tags]) + else: + #make names of tags in the input to agree with the database + + cleaned_entered_tags = set() + for entered_tag in entered_tags: + try: + #looks like we have to load tags one-by one + stored_tag = models.Tag.objects.get( + name__iexact = entered_tag + ) + cleaned_entered_tags.add(stored_tag.name) + except models.Tag.DoesNotExist: + cleaned_entered_tags.add(entered_tag) + entered_tags = list(cleaned_entered_tags) + + return u' '.join(entered_tags) class WikiField(forms.BooleanField): def __init__(self, *args, **kwargs): diff --git a/askbot/management/commands/fix_question_tags.py b/askbot/management/commands/fix_question_tags.py index 1d5cae7e..d036cfe6 100644 --- a/askbot/management/commands/fix_question_tags.py +++ b/askbot/management/commands/fix_question_tags.py @@ -2,8 +2,10 @@ import sys from django.core.management.base import NoArgsCommand from django.db import transaction from askbot import models +from askbot import forms from askbot.utils import console from askbot.models import signals +from askbot.conf import settings as askbot_settings FORMAT_STRING = '%6.2f%%' @@ -16,14 +18,32 @@ class Command(NoArgsCommand): @transaction.commit_manually def run_command(self): """method that runs the actual command""" + #go through tags and find character case duplicates and eliminate them + tagnames = models.Tag.objects.values_list('name', flat = True) + for name in tagnames: + dupes = models.Tag.objects.filter(name__iexact = name) + first_tag = dupes[0] + if dupes.count() > 1: + line = 'Found duplicate tags for %s:' % first_tag.name + for idx in xrange(1, dupes.count()): + print dupes[idx].name + ' ', + dupes[idx].delete() + print '' + if askbot_settings.FORCE_LOWERCASE_TAGS: + lowercased_name = first_tag.name.lower() + if first_tag.name != lowercased_name: + print 'Converting tag %s to lower case' % first_tag.name + first_tag.name = lowercased_name + first_tag.save() + transaction.commit() + #go through questions and fix tag records on each questions = models.Question.objects.all() checked_count = 0 found_count = 0 total_count = questions.count() - print "Searching for questions with incomplete tag records:", + print "Searching for questions with inconsistent tag records:", for question in questions: - tags = question.tags.all() denorm_tag_set = set(question.get_tag_names()) norm_tag_set = set(question.tags.values_list('name', flat=True)) @@ -36,12 +56,17 @@ class Command(NoArgsCommand): user = question.author timestamp = question.added_at + tagnames = forms.TagNamesField().clean(question.tagnames) + question.update_tags( - tagnames = question.tagnames, + tagnames = tagnames, user = user, timestamp = timestamp ) + question.tagnames = tagnames + question.save() found_count += 1 + transaction.commit() checked_count += 1 progress = 100*float(checked_count)/float(total_count) @@ -50,4 +75,4 @@ class Command(NoArgsCommand): if found_count: print '%d problem questions found, tag records restored' % found_count else: - print 'Nothing found' + print 'Did not find any problems' diff --git a/askbot/skins/default/media/js/post.js b/askbot/skins/default/media/js/post.js index 12299a82..85600a22 100644 --- a/askbot/skins/default/media/js/post.js +++ b/askbot/skins/default/media/js/post.js @@ -662,7 +662,7 @@ var questionRetagger = function(){ data: { tags: getUniqueWords(tagInput.val()).join(' ') }, success: function(json) { if (json['success'] === true){ - new_tags = getUniqueWords(tagInput.val()); + new_tags = getUniqueWords(json['new_tags']); oldTagsHtml = ''; cancelRetag(); drawNewTags(new_tags.join(' ')); diff --git a/askbot/tests/__init__.py b/askbot/tests/__init__.py index d0e70240..1cb8d37b 100644 --- a/askbot/tests/__init__.py +++ b/askbot/tests/__init__.py @@ -7,3 +7,4 @@ from askbot.tests.skin_tests import * from askbot.tests.badge_tests import * from askbot.tests.management_command_tests import * from askbot.tests.search_state_tests import * +from askbot.tests.form_tests import * diff --git a/askbot/tests/form_tests.py b/askbot/tests/form_tests.py new file mode 100644 index 00000000..dfa2d628 --- /dev/null +++ b/askbot/tests/form_tests.py @@ -0,0 +1,35 @@ +from askbot.tests.utils import AskbotTestCase +from askbot.conf import settings as askbot_settings +from askbot import forms +from askbot import models + +class TagNamesFieldTests(AskbotTestCase): + + def setUp(self): + self.field = forms.TagNamesField() + self.user = self.create_user('user1') + + def clean(self, value): + return self.field.clean(value).strip().split(' ') + + def assert_tags_equal(self, tag_list1, tag_list2): + self.assertEqual(sorted(tag_list1), sorted(tag_list2)) + + def test_force_lowercase(self): + """FORCE_LOWERCASE setting is on + """ + askbot_settings.update('FORCE_LOWERCASE_TAGS', True) + cleaned_tags = self.clean('Tag1 TAG5 tag1 tag5') + self.assert_tags_equal(cleaned_tags, ['tag1','tag5']) + + def test_custom_case(self): + """FORCE_LOWERCASE setting is off + """ + askbot_settings.update('FORCE_LOWERCASE_TAGS', False) + models.Tag(name = 'TAG1', created_by = self.user).save() + models.Tag(name = 'Tag2', created_by = self.user).save() + cleaned_tags = self.clean('tag1 taG2 TAG1 tag3 tag3') + self.assert_tags_equal(cleaned_tags, ['TAG1', 'Tag2', 'tag3']) + + + diff --git a/askbot/views/writers.py b/askbot/views/writers.py index a1c2b512..2dc3f2c8 100644 --- a/askbot/views/writers.py +++ b/askbot/views/writers.py @@ -282,7 +282,10 @@ def retag_question(request, id): tags = form.cleaned_data['tags'] ) if request.is_ajax(): - response_data = {'success': True} + response_data = { + 'success': True, + 'new_tags': question.tagnames + } data = simplejson.dumps(response_data) return HttpResponse(data, mimetype="application/json") else: -- cgit v1.2.3-1-g7c22 From 6ddb2c7c07d740e77ba78a8475495c8dc9ae3124 Mon Sep 17 00:00:00 2001 From: Evgeny Fadeev Date: Sun, 30 Jan 2011 21:21:24 -0500 Subject: added a management command to recalculate response counts for the inboxes --- askbot/doc/source/management-commands.rst | 2 + askbot/management/__init__.py | 82 ++++++++++++++++++++++++++ askbot/management/commands/fix_inbox_counts.py | 46 +++++++++++++++ 3 files changed, 130 insertions(+) create mode 100644 askbot/management/commands/fix_inbox_counts.py diff --git a/askbot/doc/source/management-commands.rst b/askbot/doc/source/management-commands.rst index 34c47155..188654bf 100644 --- a/askbot/doc/source/management-commands.rst +++ b/askbot/doc/source/management-commands.rst @@ -112,6 +112,8 @@ The commands from this section will help fix those issues. +--------------------------------+-------------------------------------------------------------+ | `fix_answer_counts` | recalculates answer counts for all questions | +--------------------------------+-------------------------------------------------------------+ +| `fix_inbox_counts` | recalculates response counts in the user inboxes | ++--------------------------------+-------------------------------------------------------------+ | `fix_revisionless_posts` | adds a revision record to posts that lack them | +--------------------------------+-------------------------------------------------------------+ | `fix_question_tags` | takes tag names from the record on the question table | diff --git a/askbot/management/__init__.py b/askbot/management/__init__.py index e69de29b..1e2b2aaf 100644 --- a/askbot/management/__init__.py +++ b/askbot/management/__init__.py @@ -0,0 +1,82 @@ +import sys +from django.core.management.base import NoArgsCommand +from django.db import transaction +from askbot.models import signals +from askbot.utils import console + +FORMAT_STRING = '%6.2f%%'#to print progress in percent + +class NoArgsJob(NoArgsCommand): + """Base class for a job command - + the one that runs the same operation on + sets of items - each item operation in its own + transaction and prints progress in % of items + completed + + The subclass must implement __init__() method + where self.batches data structure must be defined as follows + (#the whole thing is a tuple + {#batch is described by a dictionary + 'title': , + 'query_set': , + 'function': , + 'items_changed_message': , + 'nothing_changed_message': + }, + #more batch descriptions + ) + """ + batches = () + + def handle_noargs(self, **options): + """handler function that removes all signal listeners + then runs the job and finally restores the listerers + """ + signal_data = signals.pop_all_db_signal_receivers() + self.run_command(**options) + signals.set_all_db_signal_receivers(signal_data) + + def run_command(self, **options): + """runs the batches""" + for batch in self.batches: + self.run_batch(batch) + + @transaction.commit_manually + def run_batch(self, batch): + """runs the single batch + prints batch title + then loops through the query set + and prints progress in % + afterwards there will be a short summary + """ + + sys.stdout.write(batch['title']) + changed_count = 0 + checked_count = 0 + total_count = batch['query_set'].count() + + if total_count == 0: + return + + for item in batch['query_set'].all(): + + item_changed = batch['function'](item) + transaction.commit() + + if item_changed: + changed_count += 1 + checked_count += 1 + + progress = 100*float(checked_count)/float(total_count) + console.print_progress(FORMAT_STRING, progress) + print FORMAT_STRING % 100 + + if changed_count: + print batch['changed_count_message'] % changed_count + else: + print batch['nothing_changed_message'] diff --git a/askbot/management/commands/fix_inbox_counts.py b/askbot/management/commands/fix_inbox_counts.py new file mode 100644 index 00000000..c2ffffdc --- /dev/null +++ b/askbot/management/commands/fix_inbox_counts.py @@ -0,0 +1,46 @@ +from askbot.management import NoArgsJob +from askbot import models +from askbot import const + +ACTIVITY_TYPES = const.RESPONSE_ACTIVITY_TYPES_FOR_DISPLAY +ACTIVITY_TYPES += (const.TYPE_ACTIVITY_MENTION,) + +def fix_inbox_counts(user): + old_new_count = user.new_response_count + old_seen_count = user.seen_response_count + new_new_count = models.ActivityAuditStatus.objects.filter( + user = user, + status = models.ActivityAuditStatus.STATUS_NEW, + activity__activity_type__in = ACTIVITY_TYPES + ).count() + new_seen_count = models.ActivityAuditStatus.objects.filter( + user = user, + status = models.ActivityAuditStatus.STATUS_SEEN, + activity__activity_type__in = ACTIVITY_TYPES + ).count() + + (changed1, changed2) = (False, False) + if new_new_count != old_new_count: + user.new_response_count = new_new_count + changed1 = True + if new_seen_count != old_seen_count: + user.seen_response_count = new_seen_count + changed2 = True + if changed1 or changed2: + user.save() + return True + return False + +class Command(NoArgsJob): + """definition of the job that fixes response counts + destined for the user inboxes + """ + def __init__(self, *args, **kwargs): + self.batches = ({ + 'title': 'Checking inbox item counts for all users: ', + 'query_set': models.User.objects.all(), + 'function': fix_inbox_counts, + 'changed_count_message': 'Corrected records for %d users', + 'nothing_changed_message': 'No problems found' + },) + super(Command, self).__init__(*args, **kwargs) -- cgit v1.2.3-1-g7c22 From a43a653e5a80cd9116edc7d6b9e6250bcad4f6c8 Mon Sep 17 00:00:00 2001 From: Evgeny Fadeev Date: Sun, 30 Jan 2011 21:49:00 -0500 Subject: fixed the version record --- askbot/__init__.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/askbot/__init__.py b/askbot/__init__.py index 4b161e23..b084cb5b 100644 --- a/askbot/__init__.py +++ b/askbot/__init__.py @@ -19,4 +19,4 @@ def get_version(): """returns version of the askbot app this version is meaningful for pypi only """ - return '0.6.67' + return '0.6.66' -- cgit v1.2.3-1-g7c22 From fc2d51007e4a4d593a0d03dafc667759ebd64f6e Mon Sep 17 00:00:00 2001 From: Evgeny Fadeev Date: Mon, 31 Jan 2011 03:48:22 -0500 Subject: an inconsequential experiment with skin loader --- askbot/skins/loaders.py | 37 +++++++++++++++++++++++++++++++++++-- 1 file changed, 35 insertions(+), 2 deletions(-) diff --git a/askbot/skins/loaders.py b/askbot/skins/loaders.py index f264c546..47367715 100644 --- a/askbot/skins/loaders.py +++ b/askbot/skins/loaders.py @@ -5,6 +5,8 @@ from askbot.conf import settings as askbot_settings from django.conf import settings as django_settings from coffin.common import CoffinEnvironment from jinja2 import loaders as jinja_loaders +from jinja2.exceptions import TemplateNotFound +from jinja2.utils import open_if_exists from askbot.skins import utils #module for skinning askbot @@ -32,13 +34,40 @@ def load_template_source(name, dirs=None): return filesystem.load_template_source(tname,dirs) load_template_source.is_usable = True +class SkinLoader(jinja_loaders.BaseLoader): + """loads template from the skin directory + code largely copy-pasted from the jinja2 internals + """ + def get_source(self, environment, template): + pieces = jinja_loaders.split_template_path(template) + skin = askbot_settings.ASKBOT_DEFAULT_SKIN + skin_path = utils.get_path_to_skin(skin) + filename = os.path.join(skin_path, 'templates', *pieces) + print 'want file %s' % filename + f = open_if_exists(filename) + if f is None: + raise TemplateNotFound(template) + try: + contents = f.read().decode('utf-8') + finally: + f.close() + + mtime = os.path.getmtime(filename) + def uptodate(): + try: + return os.path.getmtime(filename) == mtime + except OSError: + return False + return contents, filename, uptodate + class SkinEnvironment(CoffinEnvironment): """Jinja template environment that loads templates from askbot skins """ def _get_loaders(self): - """over-ridden function _get_loaders that creates + """this method is not used + over-ridden function _get_loaders that creates the loader for the skin templates """ loaders = list() @@ -58,5 +87,9 @@ class SkinEnvironment(CoffinEnvironment): self.install_gettext_translations(trans) -ENV = SkinEnvironment(autoescape=False, extensions=['jinja2.ext.i18n']) +ENV = SkinEnvironment( + autoescape=False, + extensions=['jinja2.ext.i18n'], + #loader = SkinLoader() + ) ENV.set_language(django_settings.LANGUAGE_CODE) -- cgit v1.2.3-1-g7c22 From cc38fb000063574555fe895f26b5ddf9b5ae23bb Mon Sep 17 00:00:00 2001 From: Evgeny Fadeev Date: Mon, 31 Jan 2011 20:47:30 -0500 Subject: skins can now be switched on the go --- askbot/conf/markup.py | 10 +-------- askbot/skins/README | 2 -- askbot/skins/common/media/README | 1 - askbot/skins/loaders.py | 42 ++++++++++++++++++++++++++++++++--- askbot/skins/utils.py | 11 +++------- askbot/views/commands.py | 12 +++------- askbot/views/meta.py | 31 ++++++++------------------ askbot/views/readers.py | 25 ++++++++------------- askbot/views/users.py | 47 +++++++++++++--------------------------- askbot/views/writers.py | 23 +++++--------------- 10 files changed, 85 insertions(+), 119 deletions(-) delete mode 100755 askbot/skins/common/media/README diff --git a/askbot/conf/markup.py b/askbot/conf/markup.py index 23a2dc67..026c5536 100644 --- a/askbot/conf/markup.py +++ b/askbot/conf/markup.py @@ -15,13 +15,6 @@ MARKUP = ConfigurationGroup( _('Markup formatting') ) -mathjax_dir = os.path.join( - askbot.get_install_directory(), - 'skins', - 'common', - 'media' - ) - settings.register( BooleanValue( MARKUP, @@ -47,10 +40,9 @@ settings.register( help_text=_( 'If you enable this feature, ' 'mathjax must be ' - 'installed in directory %(dir)s' + 'installed on your server in its own directory.' ) % { 'url': const.DEPENDENCY_URLS['mathjax'], - 'dir': mathjax_dir, }, default = False ) diff --git a/askbot/skins/README b/askbot/skins/README index 01ef0a9d..42a6ea25 100755 --- a/askbot/skins/README +++ b/askbot/skins/README @@ -1,7 +1,6 @@ this directory contains available skins 1) default - default skin with templates -2) common - this directory is to media directory common to all or many templates to create a new skin just create another directory under skins/ and start populating it with the directory structure as in @@ -16,7 +15,6 @@ templates are resolved in the following way: media is resolved with one extra option * settings.ASKBOT_DEFAULT_SKIN * 'default' -* 'common' media does not have to be composed of files named the same way as in default skin whatever media you link to from your templates - will be in operation diff --git a/askbot/skins/common/media/README b/askbot/skins/common/media/README deleted file mode 100755 index 3376e754..00000000 --- a/askbot/skins/common/media/README +++ /dev/null @@ -1 +0,0 @@ -directory for media common to all or many templates diff --git a/askbot/skins/loaders.py b/askbot/skins/loaders.py index 47367715..c9a1a059 100644 --- a/askbot/skins/loaders.py +++ b/askbot/skins/loaders.py @@ -1,5 +1,7 @@ import os.path from django.template.loaders import filesystem +from django.template import RequestContext +from django.http import HttpResponse from django.utils import translation from askbot.conf import settings as askbot_settings from django.conf import settings as django_settings @@ -65,14 +67,20 @@ class SkinEnvironment(CoffinEnvironment): that loads templates from askbot skins """ + def __init__(self, *args, **kwargs): + """save the skin path and initialize the + Coffin Environment + """ + self.skin = kwargs.pop('skin') + super(SkinEnvironment, self).__init__(*args, **kwargs) + def _get_loaders(self): """this method is not used over-ridden function _get_loaders that creates the loader for the skin templates """ loaders = list() - skin_name = askbot_settings.ASKBOT_DEFAULT_SKIN - skin_dirs = utils.get_available_skins(selected = skin_name).values() + skin_dirs = utils.get_available_skins(selected = self.skin).values() template_dirs = [os.path.join(skin_dir, 'templates') for skin_dir in skin_dirs] loaders.append(jinja_loaders.FileSystemLoader(template_dirs)) @@ -86,10 +94,38 @@ class SkinEnvironment(CoffinEnvironment): trans = translation.trans_real.translation(language_code) self.install_gettext_translations(trans) - ENV = SkinEnvironment( autoescape=False, extensions=['jinja2.ext.i18n'], + skin = 'default' #loader = SkinLoader() ) ENV.set_language(django_settings.LANGUAGE_CODE) + +def load_skins(): + skins = dict() + for skin_name in utils.get_available_skins(): + skins[skin_name] = SkinEnvironment(skin = skin_name) + skins[skin_name].set_language(django_settings.LANGUAGE_CODE) + return skins + +SKINS = load_skins() + +def get_template(template, request): + """retreives template for the skin + request variable will be used in the future to set + template according to the user preference or admins preference + + at this point request variable is not used though + """ + skin = SKINS[askbot_settings.ASKBOT_DEFAULT_SKIN] + return skin.get_template(template) + +def render_into_skin(template, data, request, mimetype = 'text/html'): + """in the future this function will be able to + switch skin depending on the site administrator/user selection + right now only admins can switch + """ + context = RequestContext(request, data) + template = get_template(template, request) + return HttpResponse(template.render(context), mimetype = mimetype) diff --git a/askbot/skins/utils.py b/askbot/skins/utils.py index b244da00..a80c85ed 100644 --- a/askbot/skins/utils.py +++ b/askbot/skins/utils.py @@ -3,7 +3,6 @@ the lookup resolution process for templates and media works as follows: * look up item in selected skin * if not found look in 'default' -* the look in 'common' * raise an exception """ import os @@ -29,11 +28,10 @@ def get_skins_from_dir(directory): def get_available_skins(selected=None): """selected is a name of preferred skin if it's None, then information about all skins will be returned - otherwise, only data about selected, default and common skins + otherwise, only data about selected and default skins will be returned selected skin is guaranteed to be the first item in the dictionary - """ skins = SortedDict() if hasattr(django_settings, 'ASKBOT_EXTRA_SKINS_DIR'): @@ -42,7 +40,6 @@ def get_available_skins(selected=None): stock_dir = os.path.normpath(os.path.dirname(__file__)) stock_skins = get_skins_from_dir(stock_dir) default_dir = stock_skins.pop('default') - common_dir = stock_skins.pop('common') skins.update(stock_skins) @@ -55,9 +52,8 @@ def get_available_skins(selected=None): assert(selected == 'default') skins = SortedDict() - #re-insert default and common as last two items + #re-insert default as a last item skins['default'] = default_dir - skins['common'] = common_dir return skins @@ -75,11 +71,10 @@ def get_skin_choices(): """returns a tuple for use as a set of choices in the form""" skin_names = list(reversed(get_available_skins().keys())) - skin_names.remove('common') return zip(skin_names, skin_names) def resolve_skin_for_media(media=None, preferred_skin = None): - #see if file exists, if not, try skins 'default', then 'common' + #see if file exists, if not, try skin 'default' available_skins = get_available_skins(selected = preferred_skin).items() for skin_name, skin_dir in available_skins: if os.path.isfile(os.path.join(skin_dir, 'media', media)): diff --git a/askbot/views/commands.py b/askbot/views/commands.py index 4fdc18b2..e760080b 100644 --- a/askbot/views/commands.py +++ b/askbot/views/commands.py @@ -11,13 +11,12 @@ from django.core import exceptions from django.http import HttpResponse, HttpResponseRedirect from django.shortcuts import get_object_or_404 from django.utils.translation import ugettext as _ -from django.template import RequestContext from askbot import models from askbot.forms import CloseForm from django.core.urlresolvers import reverse from django.contrib.auth.decorators import login_required from askbot.utils.decorators import ajax_only, ajax_login_required -from askbot.skins.loaders import ENV +from askbot.skins.loaders import render_into_skin from askbot import const import logging @@ -397,10 +396,7 @@ def close(request, id):#close question else: request.user.assert_can_close_question(question) form = CloseForm() - template = ENV.get_template('close.html') - data = {'form': form, 'question': question} - context = RequestContext(request, data) - return HttpResponse(template.render(context)) + return render_into_skin('close.html', data, request) except exceptions.PermissionDenied, e: request.user.message_set.create(message = unicode(e)) return HttpResponseRedirect(question.get_absolute_url()) @@ -428,9 +424,7 @@ def reopen(request, id):#re-open question 'closed_by_profile_url': closed_by_profile_url, 'closed_by_username': closed_by_username, } - context = RequestContext(request, data) - template = ENV.get_template('reopen.html') - return HttpResponse(template.render(context)) + return render_into_skin('reopen.html', data, request) except exceptions.PermissionDenied, e: request.user.message_set.create(message = unicode(e)) diff --git a/askbot/views/meta.py b/askbot/views/meta.py index 7bd72ee6..7cc536ed 100644 --- a/askbot/views/meta.py +++ b/askbot/views/meta.py @@ -16,14 +16,13 @@ from askbot.utils.forms import get_next_url from askbot.utils.mail import mail_moderators from askbot.models import BadgeData, Award, User from askbot.models import badges as badge_data -from askbot.skins.loaders import ENV +from askbot.skins.loaders import render_into_skin from askbot.conf import settings as askbot_settings from askbot import skins def generic_view(request, template = None, page_class = None): - template = ENV.get_template(template) - context = RequestContext(request, {'page_class': page_class}) - return HttpResponse(template.render(context)) + """this may be not necessary, since it is just a rewrite of render_into_skin""" + return render_into_skin(template, {'page_class': page_class}, request) def config_variable(request, variable_name = None, mimetype = None): """Print value from the configuration settings @@ -42,15 +41,13 @@ def server_error(request, template='500.html'): return generic_view(request, template) def faq(request): - template = ENV.get_template('faq.html') data = { 'gravatar_faq_url': reverse('faq') + '#gravatar', #'send_email_key_url': reverse('send_email_key'), 'ask_question_url': reverse('ask'), 'page_class': 'meta', } - context = RequestContext(request, data) - return HttpResponse(template.render(context)) + return render_into_skin('faq.html', data, request) def feedback(request): data = {'page_class': 'meta'} @@ -71,15 +68,11 @@ def feedback(request): form = FeedbackForm(initial={'next':get_next_url(request)}) data['form'] = form - context = RequestContext(request, data) - template = ENV.get_template('feedback.html') - return HttpResponse(template.render(context)) + return render_into_skin('feedback.html', data, request) feedback.CANCEL_MESSAGE=_('We look forward to hearing your feedback! Please, give it next time :)') def privacy(request): - context = RequestContext(request, {'page_class': 'meta'}) - template = ENV.get_template('privacy.html') - return HttpResponse(template.render(context)) + return render_into_skin('privacy.html', {'page_class': 'meta'}, request) def logout(request):#refactor/change behavior? #currently you click logout and you get @@ -93,9 +86,7 @@ def logout(request):#refactor/change behavior? 'next' : get_next_url(request), 'page_class': 'meta', } - context = RequestContext(request, data) - template = ENV.get_template('logout.html') - return HttpResponse(template.render(context)) + return render_into_skin('logout.html', data, request) def badges(request):#user status/reputation system #todo: supplement database data with the stuff from badges.py @@ -110,7 +101,6 @@ def badges(request):#user status/reputation system ).distinct() #my_badges.query.group_by = ['badge_id'] - template = ENV.get_template('badges.html') data = { 'active_tab': 'badges', 'badges' : badges, @@ -118,8 +108,7 @@ def badges(request):#user status/reputation system 'mybadges' : my_badges, 'feedback_faq_url' : reverse('feedback'), } - context = RequestContext(request, data) - return HttpResponse(template.render(context)) + return render_into_skin('badges.html', data, request) def badge(request, id): #todo: supplement database data with the stuff from badges.py @@ -133,15 +122,13 @@ def badge(request, id): '-last_awarded_at' ) - template = ENV.get_template('badge.html') data = { 'active_tab': 'badges', 'badge_recipients' : badge_recipients, 'badge' : badge, 'page_class': 'meta', } - context = RequestContext(request, data) - return HttpResponse(template.render(context)) + return render_into_skin('badge.html', data, request) def media(request, skin, resource): """view that serves static media from any skin diff --git a/askbot/views/readers.py b/askbot/views/readers.py index 27fbfe78..236a7485 100644 --- a/askbot/views/readers.py +++ b/askbot/views/readers.py @@ -12,7 +12,7 @@ import urllib from django.shortcuts import get_object_or_404 from django.http import HttpResponseRedirect, HttpResponse, Http404 from django.core.paginator import Paginator, EmptyPage, InvalidPage -from django.template import RequestContext, Context +from django.template import Context from django.utils.http import urlencode from django.utils import simplejson from django.utils.translation import ugettext as _ @@ -35,7 +35,7 @@ from askbot.search.state_manager import SearchState from askbot.templatetags import extra_tags from askbot.templatetags import extra_filters import askbot.conf -from askbot.skins.loaders import ENV #jinja2 template loading enviroment +from askbot.skins.loaders import render_into_skin, get_template#jinja2 template loading enviroment # used in index page #todo: - take these out of const or settings @@ -144,7 +144,7 @@ def questions(request): } if q_count > search_state.page_size: - paginator_tpl = ENV.get_template('blocks/paginator.html') + paginator_tpl = get_template('blocks/paginator.html', request) #todo: remove this patch on context after all templates are moved to jinja paginator_context['base_url'] = request.path + '?sort=%s&' % search_state.sort data = { @@ -275,7 +275,7 @@ def questions(request): if meta_data.get('author_name',None): reset_method_count += 1 - template_context = RequestContext(request, { + template_data = { 'language_code': translation.get_language(), 'reset_method_count': reset_method_count, 'page_class': 'main-page', @@ -296,14 +296,13 @@ def questions(request): 'show_sort_by_relevance': askbot.conf.should_show_sort_by_relevance(), 'scope': search_state.scope, 'context' : paginator_context, - }) + } assert(request.is_ajax() == False) #ajax request is handled in a separate branch above #before = datetime.datetime.now() - template = ENV.get_template('questions.html') - response = HttpResponse(template.render(template_context)) + response = render_into_skin('questions.html', template_data, request) #after = datetime.datetime.now() #print after - before return response @@ -360,9 +359,7 @@ def tags(request):#view showing a listing of available tags - plain list 'keywords' : stag, 'paginator_context' : paginator_context } - context = RequestContext(request, data) - template = ENV.get_template('tags.html') - return HttpResponse(template.render(context)) + return render_into_skin('tags.html', data, request) def question(request, id):#refactor - long subroutine. display question body, answers and comments """view that displays body of the question and @@ -559,9 +556,7 @@ def question(request, id):#refactor - long subroutine. display question body, an } if request.user.is_authenticated(): data['tags_autocomplete'] = _get_tags_cache_json() - context = RequestContext(request, data) - template = ENV.get_template('question.html') - return HttpResponse(template.render(context)) + return render_into_skin('question.html', data, request) def revisions(request, id, object_name=None): assert(object_name in ('Question', 'Answer')) @@ -581,9 +576,7 @@ def revisions(request, id, object_name=None): 'post': post, 'revisions': revisions, } - context = RequestContext(request, data) - template = ENV.get_template('revisions.html') - return HttpResponse(template.render(context)) + return render_into_skin('revisions.html', data, request) @ajax_only @anonymous_forbidden diff --git a/askbot/views/users.py b/askbot/views/users.py index e68d1446..524ea33c 100644 --- a/askbot/views/users.py +++ b/askbot/views/users.py @@ -16,7 +16,6 @@ from django.core.paginator import Paginator, EmptyPage, InvalidPage from django.contrib.contenttypes.models import ContentType from django.core.urlresolvers import reverse from django.shortcuts import get_object_or_404 -from django.template import RequestContext from django.http import HttpResponse from django.http import HttpResponseRedirect, Http404 from django.utils.translation import ugettext as _ @@ -30,7 +29,7 @@ from askbot.conf import settings as askbot_settings from askbot import models from askbot import exceptions from askbot.models.badges import award_badges_signal -from askbot.skins.loaders import ENV +from askbot.skins.loaders import render_into_skin from askbot.templatetags import extra_tags question_type = ContentType.objects.get_for_model(models.Question) @@ -127,9 +126,7 @@ def users(request): 'tab_id' : sortby, 'paginator_context' : paginator_context } - template = ENV.get_template('users.html') - context = RequestContext(request, data) - return HttpResponse(template.render(context)) + return render_into_skin('users.html', data, request) def user_moderate(request, subject): """user subview for moderation @@ -222,9 +219,7 @@ def user_moderate(request, subject): 'user_rep_changed': user_rep_changed, 'user_status_changed': user_status_changed } - context = RequestContext(request, data) - template = ENV.get_template('user_profile/user_moderate.html') - return HttpResponse(template.render(context)) + return render_into_skin('user_profile/user_moderate.html', data, request) #non-view function def set_new_email(user, new_email, nomessage=False): @@ -275,9 +270,7 @@ def edit_user(request, id): 'form' : form, 'gravatar_faq_url' : reverse('faq') + '#gravatar', } - context = RequestContext(request, data) - template = ENV.get_template('user_profile/user_edit.html') - return HttpResponse(template.render(context)) + return render_into_skin('user_profile/user_edit.html', data, request) def user_stats(request, user): @@ -390,9 +383,7 @@ def user_stats(request, user): 'awarded_badge_counts': dict(awarded_badge_counts), 'total_awards' : total_awards, } - context = RequestContext(request, data) - template = ENV.get_template('user_profile/user_stats.html') - return HttpResponse(template.render(context)) + return render_into_skin('user_profile/user_stats.html', data, request) def user_recent(request, user): @@ -664,9 +655,7 @@ def user_recent(request, user): 'view_user' : user, 'activities' : activities[:const.USER_VIEW_DATA_SIZE] } - context = RequestContext(request, data) - template = ENV.get_template('user_profile/user_recent.html') - return HttpResponse(template.render(context)) + return render_into_skin('user_profile/user_recent.html', data, request) @owner_or_moderator_required def user_responses(request, user): @@ -733,9 +722,7 @@ def user_responses(request, user): 'view_user' : user, 'responses' : response_list, } - context = RequestContext(request, data) - template = ENV.get_template('user_profile/user_inbox.html') - return HttpResponse(template.render(context)) + return render_into_skin('user_profile/user_inbox.html', data, request) @owner_or_moderator_required def user_votes(request, user): @@ -799,9 +786,7 @@ def user_votes(request, user): 'view_user' : user, 'votes' : votes[:const.USER_VIEW_DATA_SIZE] } - context = RequestContext(request, data) - template = ENV.get_template('user_profile/user_votes.html') - return HttpResponse(template.render(context)) + return render_into_skin('user_profile/user_votes.html', data, request) def user_reputation(request, user): reputes = models.Repute.objects.filter(user=user).order_by('-reputed_at') @@ -838,9 +823,7 @@ def user_reputation(request, user): 'reputation': reputes, 'reps': reps } - context = RequestContext(request, data) - template = ENV.get_template('user_profile/user_reputation.html') - return HttpResponse(template.render(context)) + return render_into_skin('user_profile/user_reputation.html', data, request) def user_favorites(request, user): favorited_q_id_list= models.FavoriteQuestion.objects.filter( @@ -868,9 +851,7 @@ def user_favorites(request, user): 'favorited_myself': favorited_q_id_list, 'view_user' : user } - context = RequestContext(request, data) - template = ENV.get_template('user_profile/user_favorites.html') - return HttpResponse(template.render(context)) + return render_into_skin('user_profile/user_favorites.html', data, request) @owner_or_moderator_required def user_email_subscriptions(request, user): @@ -901,7 +882,6 @@ def user_email_subscriptions(request, user): tag_filter_form = forms.TagFilterSelectionForm(instance=user) action_status = None - template = ENV.get_template('user_profile/user_email_subscriptions.html') data = { 'active_tab': 'users', 'page_class': 'user-profile-page', @@ -913,8 +893,11 @@ def user_email_subscriptions(request, user): 'tag_filter_selection_form': tag_filter_form, 'action_status': action_status, } - context = RequestContext(request, data) - return HttpResponse(template.render(context)) + return render_into_skin( + 'user_profile/user_email_subscriptions.html', + data, + request + ) user_view_call_table = { 'stats': user_stats, diff --git a/askbot/views/writers.py b/askbot/views/writers.py index 2dc3f2c8..2bc4d3a3 100644 --- a/askbot/views/writers.py +++ b/askbot/views/writers.py @@ -16,7 +16,6 @@ from django.core.files.storage import FileSystemStorage from django.shortcuts import get_object_or_404 from django.contrib.auth.decorators import login_required from django.http import HttpResponseRedirect, HttpResponse, HttpResponseForbidden, Http404 -from django.template import RequestContext from django.utils import simplejson from django.utils.html import strip_tags from django.utils.translation import ugettext as _ @@ -27,7 +26,7 @@ from django.conf import settings from askbot.views.readers import _get_tags_cache_json from askbot import forms from askbot import models -from askbot.skins.loaders import ENV +from askbot.skins.loaders import render_into_skin from askbot.utils.decorators import ajax_only from askbot.utils.functions import diff_date from askbot.templatetags import extra_filters_jinja as template_filters @@ -180,13 +179,11 @@ def import_data(request): else: form = forms.DumpUploadForm() - template = ENV.get_template('import_data.html') data = { 'dump_upload_form': form, 'need_configuration': (not stackexchange.is_ready()) } - context = RequestContext(request, data) - return HttpResponse(template.render(context)) + return render_into_skin('import_data.html', data, request) #@login_required #actually you can post anonymously, but then must register def ask(request):#view used to ask a new question @@ -255,15 +252,13 @@ def ask(request):#view used to ask a new question form.initial['title'] = query tags = _get_tags_cache_json() - template = ENV.get_template('ask.html') data = { 'active_tab': 'ask', 'form' : form, 'tags' : tags, 'email_validation_faq_url':reverse('faq') + '#validate', } - context = RequestContext(request, data) - return HttpResponse(template.render(context)) + return render_into_skin('ask.html', data, request) @login_required def retag_question(request, id): @@ -306,9 +301,7 @@ def retag_question(request, id): 'form' : form, 'tags' : _get_tags_cache_json(), } - context = RequestContext(request, data) - template = ENV.get_template('question_retag.html') - return HttpResponse(template.render(context)) + return render_into_skin('question_retag.html', data, request) except exceptions.PermissionDenied, e: if request.is_ajax(): response_data = { @@ -366,9 +359,7 @@ def edit_question(request, id): 'form' : form, 'tags' : _get_tags_cache_json() } - context = RequestContext(request, data) - template = ENV.get_template('question_edit.html') - return HttpResponse(template.render(context)) + return render_into_skin('question_edit.html', data, request) except exceptions.PermissionDenied, e: request.user.message_set.create(message = unicode(e)) @@ -417,15 +408,13 @@ def edit_answer(request, id): else: revision_form = forms.RevisionForm(answer, latest_revision) form = forms.EditAnswerForm(answer, latest_revision) - template = ENV.get_template('answer_edit.html') data = { 'active_tab': 'questions', 'answer': answer, 'revision_form': revision_form, 'form': form, } - context = RequestContext(request, data) - return HttpResponse(template.render(context)) + return render_into_skin('answer_edit.html', data, request) except exceptions.PermissionDenied, e: request.user.message_set.create(message = unicode(e)) -- cgit v1.2.3-1-g7c22