def test_thread_summary_locmem_cache(self): cache.cache = LocMemCache('', {}) # Enable local caching thread = self.q.thread key = thread.get_summary_cache_key() self.assertTrue(thread.summary_html_cached()) self.assertIsNotNone(thread.get_cached_summary_html()) ### cache.cache.delete(key) # let's start over self.assertFalse(thread.summary_html_cached()) self.assertIsNone(thread.get_cached_summary_html()) context = { 'thread': thread, 'question': self.q, 'search_state': DummySearchState(), 'visitor': None } html = get_template('widgets/question_summary.html').render(Context(context)) filled_html = html.replace('<<<tag1>>>', SearchState.get_empty().add_tag('tag1').full_url())\ .replace('<<<tag2>>>', SearchState.get_empty().add_tag('tag2').full_url())\ .replace('<<<tag3>>>', SearchState.get_empty().add_tag('tag3').full_url()) self.assertEqual(filled_html, thread.get_summary_html(search_state=SearchState.get_empty())) self.assertTrue(thread.summary_html_cached()) self.assertEqual(html, thread.get_cached_summary_html()) ### cache.cache.set(key, 'Test <<<tag1>>>', timeout=100) self.assertTrue(thread.summary_html_cached()) self.assertEqual('Test <<<tag1>>>', thread.get_cached_summary_html()) self.assertEqual( 'Test %s' % SearchState.get_empty().add_tag('tag1').full_url(), thread.get_summary_html(search_state=SearchState.get_empty()) ) ### cache.cache.set(key, 'TestBBB <<<tag1>>>', timeout=100) self.assertTrue(thread.summary_html_cached()) self.assertEqual('TestBBB <<<tag1>>>', thread.get_cached_summary_html()) self.assertEqual( 'TestBBB %s' % SearchState.get_empty().add_tag('tag1').full_url(), thread.get_summary_html(search_state=SearchState.get_empty()) ) ### cache.cache.delete(key) thread.update_summary_html = lambda dummy: "Monkey-patched <<<tag2>>>" self.assertFalse(thread.summary_html_cached()) self.assertIsNone(thread.get_cached_summary_html()) self.assertEqual( 'Monkey-patched %s' % SearchState.get_empty().add_tag('tag2').full_url(), thread.get_summary_html(search_state=SearchState.get_empty()) )
def test_run_adv_search_ANDing_tags(self): ss = SearchState.get_empty() qs, meta_data = Thread.objects.run_advanced_search( request_user=self.user, search_state=ss.add_tag('tag1')) self.assertEqual(2, qs.count()) qs, meta_data = Thread.objects.run_advanced_search( request_user=self.user, search_state=ss.add_tag('tag1').add_tag('tag3')) self.assertEqual(2, qs.count()) qs, meta_data = Thread.objects.run_advanced_search( request_user=self.user, search_state=ss.add_tag('tag1').add_tag('tag3').add_tag('tag6')) self.assertEqual(1, qs.count()) ss = SearchState(scope=None, sort=None, query="#tag3", tags='tag1, tag6', author=None, page=None, user_logged_in=None) qs, meta_data = Thread.objects.run_advanced_search( request_user=self.user, search_state=ss) self.assertEqual(1, qs.count())
def test_thread_summary_locmem_cache(self): cache.cache = LocMemCache('', {}) # Enable local caching thread = self.q.thread key = Thread.SUMMARY_CACHE_KEY_TPL % thread.id self.assertTrue(thread.summary_html_cached()) self.assertIsNotNone(thread.get_cached_summary_html()) ### cache.cache.delete(key) # let's start over self.assertFalse(thread.summary_html_cached()) self.assertIsNone(thread.get_cached_summary_html()) context = { 'thread': thread, 'question': self.q, 'search_state': DummySearchState(), } html = get_template('widgets/question_summary.html').render(context) filled_html = html.replace('<<<tag1>>>', SearchState.get_empty().add_tag('tag1').full_url())\ .replace('<<<tag2>>>', SearchState.get_empty().add_tag('tag2').full_url())\ .replace('<<<tag3>>>', SearchState.get_empty().add_tag('tag3').full_url()) self.assertEqual( filled_html, thread.get_summary_html(search_state=SearchState.get_empty())) self.assertTrue(thread.summary_html_cached()) self.assertEqual(html, thread.get_cached_summary_html()) ### cache.cache.set(key, 'Test <<<tag1>>>', timeout=100) self.assertTrue(thread.summary_html_cached()) self.assertEqual('Test <<<tag1>>>', thread.get_cached_summary_html()) self.assertEqual( 'Test %s' % SearchState.get_empty().add_tag('tag1').full_url(), thread.get_summary_html(search_state=SearchState.get_empty())) ### cache.cache.set(key, 'TestBBB <<<tag1>>>', timeout=100) self.assertTrue(thread.summary_html_cached()) self.assertEqual('TestBBB <<<tag1>>>', thread.get_cached_summary_html()) self.assertEqual( 'TestBBB %s' % SearchState.get_empty().add_tag('tag1').full_url(), thread.get_summary_html(search_state=SearchState.get_empty())) ### cache.cache.delete(key) thread.update_summary_html = lambda dummy: "Monkey-patched <<<tag2>>>" self.assertFalse(thread.summary_html_cached()) self.assertIsNone(thread.get_cached_summary_html()) self.assertEqual( 'Monkey-patched %s' % SearchState.get_empty().add_tag('tag2').full_url(), thread.get_summary_html(search_state=SearchState.get_empty()))
def test_edge_cases_1(self): ss = SearchState( scope="favorite", # this is not a valid choice for non-logger users sort="age-desc", query=" alfa", tags="miki, mini", author="12", page="2", user_logged_in=False, ) self.assertEqual("scope:all/sort:age-desc/query:alfa/tags:miki,mini/author:12/page:2/", ss.query_string()) self.assertEqual( "scope:all/sort:age-desc/query:alfa/tags:miki,mini/author:12/page:2/", ss.deepcopy().query_string() ) ss = SearchState( scope="favorite", sort="age-desc", query=" alfa", tags="miki, mini", author="12", page="2", user_logged_in=True, ) self.assertEqual("scope:favorite/sort:age-desc/query:alfa/tags:miki,mini/author:12/page:2/", ss.query_string()) self.assertEqual( "scope:favorite/sort:age-desc/query:alfa/tags:miki,mini/author:12/page:2/", ss.deepcopy().query_string() )
def test_edge_cases_1(self): ss = SearchState( scope='favorite', # this is not a valid choice for non-logger users sort='age-desc', query=' alfa', tags='miki, mini', author='12', page='2', user_logged_in=False ) self.assertEqual( 'scope:all/sort:age-desc/query:alfa/tags:miki,mini/author:12/page:2/', ss.query_string() ) ss = SearchState( scope='favorite', sort='age-desc', query=' alfa', tags='miki, mini', author='12', page='2', user_logged_in=True ) self.assertEqual( 'scope:favorite/sort:age-desc/query:alfa/tags:miki,mini/author:12/page:2/', ss.query_string() )
def test_thread_summary_locmem_cache(self): cache.cache = LocMemCache("", {}) # Enable local caching thread = self.q.thread key = thread.get_summary_cache_key() self.assertTrue(thread.summary_html_cached()) self.assertIsNotNone(thread.get_cached_summary_html()) ### cache.cache.delete(key) # let's start over self.assertFalse(thread.summary_html_cached()) self.assertIsNone(thread.get_cached_summary_html()) context = {"thread": thread, "question": self.q, "search_state": DummySearchState(), "visitor": None} html = get_template("widgets/question_summary.html").render(Context(context)) filled_html = ( html.replace("<<<tag1>>>", SearchState.get_empty().add_tag("tag1").full_url()) .replace("<<<tag2>>>", SearchState.get_empty().add_tag("tag2").full_url()) .replace("<<<tag3>>>", SearchState.get_empty().add_tag("tag3").full_url()) ) self.assertEqual(filled_html, thread.get_summary_html(search_state=SearchState.get_empty())) self.assertTrue(thread.summary_html_cached()) self.assertEqual(html, thread.get_cached_summary_html()) ### cache.cache.set(key, "Test <<<tag1>>>", timeout=100) self.assertTrue(thread.summary_html_cached()) self.assertEqual("Test <<<tag1>>>", thread.get_cached_summary_html()) self.assertEqual( "Test %s" % SearchState.get_empty().add_tag("tag1").full_url(), thread.get_summary_html(search_state=SearchState.get_empty()), ) ### cache.cache.set(key, "TestBBB <<<tag1>>>", timeout=100) self.assertTrue(thread.summary_html_cached()) self.assertEqual("TestBBB <<<tag1>>>", thread.get_cached_summary_html()) self.assertEqual( "TestBBB %s" % SearchState.get_empty().add_tag("tag1").full_url(), thread.get_summary_html(search_state=SearchState.get_empty()), ) ### cache.cache.delete(key) thread.update_summary_html = lambda dummy: "Monkey-patched <<<tag2>>>" self.assertFalse(thread.summary_html_cached()) self.assertIsNone(thread.get_cached_summary_html()) self.assertEqual( "Monkey-patched %s" % SearchState.get_empty().add_tag("tag2").full_url(), thread.get_summary_html(search_state=SearchState.get_empty()), )
class SearchStateTests(TestCase): def setUp(self): self.state = SearchState() self.log = ViewLog() def visit_page(self, page_name): """page_name is name of the view function that is to be "visited" """ self.log.set_current(page_name) def update(self, data, user = None): self.visit_page('questions') if user is None: user = AnonymousUser() self.state.update(data, self.log, user) def add_tag(self, tag): self.update({'tags': set([tag])}) def remove_tag(self, tag): self.update({'remove_tag': tag}) def assert_tags_are(self, *args): self.assertEqual(self.state.tags, set(args)) def test_add_remove_tags(self): self.add_tag('tag1') self.assert_tags_are('tag1') self.add_tag('tag2') self.assert_tags_are('tag1', 'tag2') self.add_tag('tag3') self.assert_tags_are('tag1', 'tag2', 'tag3') self.remove_tag('tag3') self.assert_tags_are('tag1', 'tag2') self.remove_tag('tag2') self.assert_tags_are('tag1') self.remove_tag('tag1') self.assertEqual(len(self.state.tags), 0) def test_query_and_tags1(self): self.update({'query': 'hahaha'}) self.add_tag('tag1') self.assertEquals(self.state.query, 'hahaha') self.assert_tags_are('tag1') self.update({'reset_query':True}) self.assertEquals(self.state.query, None) self.assert_tags_are('tag1') def test_auto_reset_sort(self): self.update({'sort': 'age-asc'}) self.assertEquals(self.state.sort, 'age-asc') self.update({}) self.assertEquals(self.state.sort, DEFAULT_SORT)
def test_prevent_dupped_tags(self): ss = SearchState(scope=None, sort=None, query=None, tags='valid1,dupped,valid2,dupped', author=None, page=None, user_logged_in=False) self.assertEqual( 'scope:all/sort:activity-desc/tags:valid1,dupped,valid2/page:1/', ss.query_string())
class SearchStateTests(TestCase): def setUp(self): self.state = SearchState() self.log = ViewLog() def visit_page(self, page_name): """page_name is name of the view function that is to be "visited" """ self.log.set_current(page_name) def update(self, data, user=None): self.visit_page("questions") if user is None: user = AnonymousUser() self.state.update(data, self.log, user) def add_tag(self, tag): self.update({"tags": set([tag])}) def remove_tag(self, tag): self.update({"remove_tag": tag}) def assert_tags_are(self, *args): self.assertEqual(self.state.tags, set(args)) def test_add_remove_tags(self): self.add_tag("tag1") self.assert_tags_are("tag1") self.add_tag("tag2") self.assert_tags_are("tag1", "tag2") self.add_tag("tag3") self.assert_tags_are("tag1", "tag2", "tag3") self.remove_tag("tag3") self.assert_tags_are("tag1", "tag2") self.remove_tag("tag2") self.assert_tags_are("tag1") self.remove_tag("tag1") self.assertEqual(len(self.state.tags), 0) def test_query_and_tags1(self): self.update({"query": "hahaha"}) self.add_tag("tag1") self.assertEquals(self.state.query, "hahaha") self.assert_tags_are("tag1") self.update({"reset_query": True}) self.assertEquals(self.state.query, None) self.assert_tags_are("tag1") def test_auto_reset_sort(self): self.update({"sort": "age-asc"}) self.assertEquals(self.state.sort, "age-asc") self.update({}) self.assertEquals(self.state.sort, DEFAULT_SORT)
def questions(request): """ List of Questions, Tagged questions, and Unanswered questions. matching search query or user selection """ try: author_id = int(request.GET.get("author")) except (ValueError, TypeError): author_id = None try: page = int(request.GET.get("page")) except (ValueError, TypeError): page = None search_state = SearchState( scope=request.GET.get('scope', 'all'), sort=request.GET.get('sort', 'activity-desc'), query=request.GET.get('query', None), tags=request.GET.get('tags', None), author=author_id, page=page, user_logged_in=request.user.is_authenticated(), ) qs, meta_data = models.Thread.objects.run_advanced_search( request_user=request.user, search_state=search_state ) if meta_data['non_existing_tags']: search_state = search_state.remove_tags(meta_data['non_existing_tags']) #exludes the question from groups #global_group = models.Group.objects.get_global_group() #qs = qs.exclude(~Q(groups__id=global_group.id)) page_size = askbot_settings.DEFAULT_QUESTIONS_PAGE_SIZE paginator = Paginator(qs, page_size) if paginator.num_pages < search_state.page: search_state.page = 1 page = paginator.page(search_state.page) question_list = list() for thread in page.object_list: datum = get_question_data(thread) question_list.append(datum) ajax_data = { 'count': paginator.count, 'pages' : paginator.num_pages, 'questions': question_list } response_data = simplejson.dumps(ajax_data) return HttpResponse(response_data, content_type='application/json')
def questions(request): """ List of Questions, Tagged questions, and Unanswered questions. matching search query or user selection """ try: author_id = int(request.GET.get("author")) except (ValueError, TypeError): author_id = None try: page = int(request.GET.get("page")) except (ValueError, TypeError): page = None search_state = SearchState( scope=request.GET.get('scope', 'all'), sort=request.GET.get('sort', 'activity-desc'), query=request.GET.get('query', None), tags=request.GET.get('tags', None), author=author_id, page=page, user_logged_in=request.user.is_authenticated(), ) qs, meta_data = models.Thread.objects.run_advanced_search( request_user=request.user, search_state=search_state ) if meta_data['non_existing_tags']: search_state = search_state.remove_tags(meta_data['non_existing_tags']) # exludes the question from groups # global_group = models.Group.objects.get_global_group() # qs = qs.exclude(~Q(groups__id=global_group.id)) page_size = askbot_settings.DEFAULT_QUESTIONS_PAGE_SIZE paginator = Paginator(qs, page_size) if paginator.num_pages < search_state.page: search_state.page = 1 page = paginator.page(search_state.page) question_list = list() for thread in page.object_list: datum = get_question_data(thread) question_list.append(datum) ajax_data = { 'count': paginator.count, 'pages': paginator.num_pages, 'questions': question_list } response_data = simplejson.dumps(ajax_data) return HttpResponse(response_data, content_type='application/json')
def test_buggy_selectors(self): ss = SearchState( scope="blah1", sort="blah2", query=None, tags=None, # INFO: URLs for the following selectors accept only digits! author=None, page="0", user_logged_in=False, ) self.assertEqual("scope:all/sort:activity-desc/page:1/", ss.query_string()) # search defaults
def test_deep_copy_1(self): # deepcopy() is tested in other tests as well, but this is a dedicated test # just to make sure in one place that everything is ok: # 1. immutable properties (strings, ints) are just assigned to the copy # 2. lists are cloned so that change in the copy doesn't affect the original ss = SearchState( scope='unanswered', sort='votes-desc', query='hejho # tag1 [tag: tag2] @user @user2 title:"what is this?"', tags='miki, mini', author='12', page='2', user_logged_in=False ) ss2 = ss.deepcopy() self.assertEqual(ss.scope, 'unanswered') self.assertTrue(ss.scope is ss2.scope) self.assertEqual(ss.sort, 'votes-desc') self.assertTrue(ss.sort is ss2.sort) self.assertEqual(ss.query, 'hejho # tag1 [tag: tag2] @user @user2 title:"what is this?"') self.assertTrue(ss.query is ss2.query) self.assertFalse(ss.tags is ss2.tags) self.assertItemsEqual(ss.tags, ss2.tags) self.assertEqual(ss.author, 12) self.assertTrue(ss.author is ss2.author) self.assertEqual(ss.page, 2) self.assertTrue(ss.page is ss2.page) self.assertEqual(ss.stripped_query, 'hejho') self.assertTrue(ss.stripped_query is ss2.stripped_query) self.assertItemsEqual(ss.query_tags, ['tag1', 'tag2']) self.assertFalse(ss.query_tags is ss2.query_tags) self.assertItemsEqual(ss.query_users, ['user', 'user2']) self.assertFalse(ss.query_users is ss2.query_users) self.assertEqual(ss.query_title, 'what is this?') self.assertTrue(ss.query_title is ss2.query_title) self.assertEqual(ss._questions_url, urlresolvers.reverse('questions')) self.assertTrue(ss._questions_url is ss2._questions_url)
def test_deep_copy_1(self): # deepcopy() is tested in other tests as well, but this is a dedicated test # just to make sure in one place that everything is ok: # 1. immutable properties (strings, ints) are just assigned to the copy # 2. lists are cloned so that change in the copy doesn't affect the original ss = SearchState( scope='unanswered', sort='votes-desc', query='hejho #tag1 [tag: tag2] @user @user2 title:"what is this?"', tags='miki, mini', author='12', page='2', user_logged_in=False) ss2 = ss.deepcopy() self.assertEqual(ss.scope, 'unanswered') self.assertTrue(ss.scope is ss2.scope) self.assertEqual(ss.sort, 'votes-desc') self.assertTrue(ss.sort is ss2.sort) self.assertEqual( ss.query, 'hejho #tag1 [tag: tag2] @user @user2 title:"what is this?"') self.assertTrue(ss.query is ss2.query) self.assertFalse(ss.tags is ss2.tags) self.assertCountEqual(ss.tags, ss2.tags) self.assertEqual(ss.author, 12) self.assertTrue(ss.author is ss2.author) self.assertEqual(ss.page, 2) self.assertTrue(ss.page is ss2.page) self.assertEqual(ss.stripped_query, 'hejho') self.assertTrue(ss.stripped_query is ss2.stripped_query) self.assertCountEqual(ss.query_tags, ['tag1', 'tag2']) self.assertFalse(ss.query_tags is ss2.query_tags) self.assertCountEqual(ss.query_users, ['user', 'user2']) self.assertFalse(ss.query_users is ss2.query_users) self.assertEqual(ss.query_title, 'what is this?') self.assertTrue(ss.query_title is ss2.query_title) self.assertEqual(ss._questions_url, reverse('questions')) self.assertTrue(ss._questions_url is ss2._questions_url)
def test_edge_cases_1(self): ss = SearchState( scope='followed', # this is not a valid choice for non-logger users sort='age-desc', query=' alfa', tags='miki, mini', author='12', page='2', user_logged_in=False) self.assertEqual( 'scope:all/sort:age-desc/tags:miki,mini/author:12/page:2/query:alfa/', ss.query_string()) self.assertEqual( 'scope:all/sort:age-desc/tags:miki,mini/author:12/page:2/query:alfa/', ss.deepcopy().query_string()) ss = SearchState(scope='followed', sort='age-desc', query=' alfa', tags='miki, mini', author='12', page='2', user_logged_in=True) self.assertEqual( 'scope:followed/sort:age-desc/tags:miki,mini/author:12/page:2/query:alfa/', ss.query_string()) self.assertEqual( 'scope:followed/sort:age-desc/tags:miki,mini/author:12/page:2/query:alfa/', ss.deepcopy().query_string())
def test_buggy_selectors(self): ss = SearchState( scope='blah1', sort='blah2', query=None, tags=None, # INFO: URLs for the following selectors accept only digits! author=None, page='0', user_logged_in=False) self.assertEqual( 'scope:all/sort:activity-desc/page:1/', # search defaults ss.query_string())
def test_all_valid_selectors(self): ss = SearchState(scope='unanswered', sort='age-desc', query=' alfa', tags='miki, mini', author='12', page='2', user_logged_in=False) self.assertEqual( 'scope:unanswered/sort:age-desc/tags:miki,mini/author:12/page:2/query:alfa/', ss.query_string()) self.assertEqual( 'scope:unanswered/sort:age-desc/tags:miki,mini/author:12/page:2/query:alfa/', ss.deepcopy().query_string())
def test_prevent_dupped_tags(self): ss = SearchState( scope=None, sort=None, query=None, tags='valid1,dupped,valid2,dupped', author=None, page=None, user_logged_in=False ) self.assertEqual( 'scope:all/sort:activity-desc/tags:valid1,dupped,valid2/page:1/', ss.query_string() )
def test_deep_copy_1(self): # deepcopy() is tested in other tests as well, but this is a dedicated test # just to make sure in one place that everything is ok: # 1. immutable properties (strings, ints) are just assigned to the copy # 2. lists are cloned so that change in the copy doesn't affect the original ss = SearchState( scope="unanswered", sort="votes-desc", query='hejho #tag1 [tag: tag2] @user @user2 title:"what is this?"', tags="miki, mini", author="12", page="2", user_logged_in=False, ) ss2 = ss.deepcopy() self.assertEqual(ss.scope, "unanswered") self.assertTrue(ss.scope is ss2.scope) self.assertEqual(ss.sort, "votes-desc") self.assertTrue(ss.sort is ss2.sort) self.assertEqual(ss.query, 'hejho #tag1 [tag: tag2] @user @user2 title:"what is this?"') self.assertTrue(ss.query is ss2.query) self.assertFalse(ss.tags is ss2.tags) self.assertItemsEqual(ss.tags, ss2.tags) self.assertEqual(ss.author, 12) self.assertTrue(ss.author is ss2.author) self.assertEqual(ss.page, 2) self.assertTrue(ss.page is ss2.page) self.assertEqual(ss.stripped_query, "hejho") self.assertTrue(ss.stripped_query is ss2.stripped_query) self.assertItemsEqual(ss.query_tags, ["tag1", "tag2"]) self.assertFalse(ss.query_tags is ss2.query_tags) self.assertItemsEqual(ss.query_users, ["user", "user2"]) self.assertFalse(ss.query_users is ss2.query_users) self.assertEqual(ss.query_title, "what is this?") self.assertTrue(ss.query_title is ss2.query_title) self.assertEqual(ss._questions_url, urlresolvers.reverse("questions")) self.assertTrue(ss._questions_url is ss2._questions_url)
def test_all_valid_selectors(self): ss = SearchState( scope='unanswered', sort='age-desc', query=' alfa', tags='miki, mini', author='12', page='2', user_logged_in=False ) self.assertEqual( 'scope:unanswered/sort:age-desc/query:alfa/tags:miki,mini/author:12/page:2/', ss.query_string() )
def get_context_data(self, **kwargs): context = QuestionView.get_context_data(self, **kwargs) self.context_instance = self.get_context_object_instance(**kwargs) try: self.current_question = SpecificQuestion.objects.get( type__in=self.get_specific_types(), content_type=ContentType.objects.get_for_model( self.context_instance), object_id=self.context_instance.id, thread=Post.objects.get(id=kwargs["question_id"]).thread) except SpecificQuestion.DoesNotExist: raise Http404 search_state = SearchState.get_empty() search_state._questions_url = self.get_questions_url() context.update({ 'current_question': self.current_question, 'current_question_url': self.get_question_url(), 'form_answer_url': self.get_answer_url(), 'edit_question_url': self.get_edit_url(), 'search_state': search_state, 'disable_retag': True, }) return context
def test_run_adv_search_url_author(self): ss = SearchState(scope=None, sort=None, query=None, tags=None, author=self.user.id, page=None, user_logged_in=None) qs, meta_data = Thread.objects.run_advanced_search(request_user=self.user, search_state=ss) self.assertEqual(2, len(qs)) self.assertEqual(self.q1.thread_id, min(qs[0].id, qs[1].id)) self.assertEqual(self.q2.thread_id, max(qs[0].id, qs[1].id)) ss = SearchState(scope=None, sort=None, query=None, tags=None, author=self.user2.id, page=None, user_logged_in=None) qs, meta_data = Thread.objects.run_advanced_search(request_user=self.user, search_state=ss) self.assertEqual(1, len(qs)) self.assertEqual(self.q3.thread_id, qs[0].id) ss = SearchState(scope=None, sort=None, query=None, tags=None, author=self.user3.id, page=None, user_logged_in=None) qs, meta_data = Thread.objects.run_advanced_search(request_user=self.user, search_state=ss) self.assertEqual(1, len(qs)) self.assertEqual(self.q4.thread_id, qs[0].id)
def tag_widget(tag, **kwargs): kwargs['tag'] = tag kwargs.setdefault('html_tag', 'div') kwargs.setdefault('is_link', True) if kwargs.get('search_state') is None: kwargs['search_state'] = SearchState.get_empty() return kwargs
def get_context_data(self, **kwargs): context = QuestionView.get_context_data(self, **kwargs) self.context_instance = self.get_context_object_instance(**kwargs) try: self.current_question = SpecificQuestion.objects.get(type__in=self.get_specific_types(), content_type=ContentType.objects.get_for_model(self.context_instance), object_id=self.context_instance.id, thread=Post.objects.get(id=kwargs["question_id"]).thread) except SpecificQuestion.DoesNotExist: raise Http404 search_state = SearchState.get_empty() search_state._questions_url = self.get_questions_url() context.update({ 'current_question': self.current_question, 'current_question_url': self.get_question_url(), 'form_answer_url': self.get_answer_url(), 'edit_question_url': self.get_edit_url(), 'search_state': search_state, 'disable_retag': True, }) return context
def test_edge_cases_2(self): old_func = askbot.conf.should_show_sort_by_relevance askbot.conf.should_show_sort_by_relevance = lambda: True # monkey patch ss = SearchState( scope='all', sort='relevance-desc', query='hejho', tags='miki, mini', author='12', page='2', user_logged_in=False ) self.assertEqual( 'scope:all/sort:relevance-desc/tags:miki,mini/author:12/page:2/query:hejho/', ss.query_string() ) ss = SearchState( scope='all', sort='relevance-desc', # this is not a valid choice for empty queries query=None, tags='miki, mini', author='12', page='2', user_logged_in=False ) self.assertEqual( 'scope:all/sort:activity-desc/tags:miki,mini/author:12/page:2/', ss.query_string() ) askbot.conf.should_show_sort_by_relevance = lambda: False # monkey patch ss = SearchState( scope='all', sort='relevance-desc', # this is also invalid for db-s other than Postgresql query='hejho', tags='miki, mini', author='12', page='2', user_logged_in=False ) self.assertEqual( 'scope:all/sort:activity-desc/tags:miki,mini/author:12/page:2/query:hejho/', ss.query_string() ) askbot.conf.should_show_sort_by_relevance = old_func
def _ss(self, query=None, tags=None): return SearchState(scope=None, sort=None, query=query, tags=tags, author=None, page=None, user_logged_in=False)
def user(request, id, slug=None, tab_name=None): """Main user view function that works as a switchboard id - id of the profile owner todo: decide what to do with slug - it is not used in the code in any way """ profile_owner = get_object_or_404(models.User, id = id) if slugify(profile_owner.username) != slug: view_url = profile_owner.get_profile_url() + '?' \ + urllib.urlencode(request.REQUEST) return HttpResponseRedirect(view_url) if not tab_name: tab_name = request.GET.get('sort', 'stats') if askbot_settings.KARMA_MODE == 'public': can_show_karma = True elif askbot_settings.KARMA_MODE == 'hidden': can_show_karma = False else: if request.user.is_anonymous(): can_show_karma = False elif request.user.is_administrator_or_moderator(): can_show_karma = True elif request.user == profile_owner: can_show_karma = True else: can_show_karma = False if can_show_karma == False and tab_name == 'reputation': raise Http404 user_view_func = USER_VIEW_CALL_TABLE.get(tab_name, user_stats) search_state = SearchState( scope=None, sort=None, query=None, tags=None, author=None, page=None, page_size=const.USER_POSTS_PAGE_SIZE, user_logged_in=profile_owner.is_authenticated(), ) context = { 'view_user': profile_owner, 'can_show_karma': can_show_karma, 'search_state': search_state, 'user_follow_feature_on': ('followit' in django_settings.INSTALLED_APPS), } if CUSTOM_TAB: context['custom_tab_name'] = CUSTOM_TAB['NAME'] context['custom_tab_slug'] = CUSTOM_TAB['SLUG'] return user_view_func(request, profile_owner, context)
def test_deep_copy_2(self): # Regression test: a special case of deepcopy() when `tags` list is empty, # there was a bug before where this empty list in original and copy pointed # to the same list object ss = SearchState.get_empty() ss2 = ss.deepcopy() self.assertFalse(ss.tags is ss2.tags) self.assertCountEqual(ss.tags, ss2.tags) self.assertCountEqual([], ss2.tags)
def test_deep_copy_2(self): # Regression test: a special case of deepcopy() when `tags` list is empty, # there was a bug before where this empty list in original and copy pointed # to the same list object ss = SearchState.get_empty() ss2 = ss.deepcopy() self.assertFalse(ss.tags is ss2.tags) self.assertItemsEqual(ss.tags, ss2.tags) self.assertItemsEqual([], ss2.tags)
def test_edge_cases_2(self): old_func = askbot.conf.should_show_sort_by_relevance askbot.conf.should_show_sort_by_relevance = lambda: True # monkey patch ss = SearchState( scope="all", sort="relevance-desc", query="hejho", tags="miki, mini", author="12", page="2", user_logged_in=False, ) self.assertEqual( "scope:all/sort:relevance-desc/query:hejho/tags:miki,mini/author:12/page:2/", ss.query_string() ) ss = SearchState( scope="all", sort="relevance-desc", # this is not a valid choice for empty queries query=None, tags="miki, mini", author="12", page="2", user_logged_in=False, ) self.assertEqual("scope:all/sort:activity-desc/tags:miki,mini/author:12/page:2/", ss.query_string()) askbot.conf.should_show_sort_by_relevance = lambda: False # monkey patch ss = SearchState( scope="all", sort="relevance-desc", # this is also invalid for db-s other than Postgresql query="hejho", tags="miki, mini", author="12", page="2", user_logged_in=False, ) self.assertEqual("scope:all/sort:activity-desc/query:hejho/tags:miki,mini/author:12/page:2/", ss.query_string()) askbot.conf.should_show_sort_by_relevance = old_func
def test_thread_caching_1(self): ss = SearchState.get_empty() qs, meta_data = Thread.objects.run_advanced_search(request_user=self.user, search_state=ss) qs = list(qs) for thread in qs: self.assertIsNone(getattr(thread, '_question_cache', None)) self.assertIsNone(getattr(thread, '_last_activity_by_cache', None)) post = Post.objects.get(post_type='question', thread=thread.id) self.assertEqual(post, thread._question_post()) self.assertEqual(post, thread._question_cache) self.assertTrue(thread._question_post() is thread._question_cache)
def test_thread_caching_1(self): ss = SearchState.get_empty() qs, meta_data = Thread.objects.run_advanced_search(request_user=self.user, search_state=ss) qs = list(qs) for thread in qs: self.assertIsNone(getattr(thread, "_question_cache", None)) self.assertIsNone(getattr(thread, "_last_activity_by_cache", None)) post = Post.objects.get(post_type="question", thread=thread.id) self.assertEqual(post, thread._question_post()) self.assertEqual(post, thread._question_cache) self.assertTrue(thread._question_post() is thread._question_cache)
def test_thread_summary_rendering_dummy_cache(self): cache.cache = DummyCache('', {}) # Disable caching ss = SearchState.get_empty() thread = self.q.thread test_html = thread.get_summary_html(search_state=ss) context = { 'thread': thread, 'question': thread._question_post(), 'search_state': ss, 'visitor': None } proper_html = get_template('widgets/question_summary.html').render( context) self.assertEqual(test_html, proper_html) # Make double-check that all tags are included self.assertTrue(ss.add_tag('tag1').full_url() in test_html) self.assertTrue(ss.add_tag('tag2').full_url() in test_html) self.assertTrue(ss.add_tag('tag3').full_url() in test_html) self.assertFalse(ss.add_tag('mini-mini').full_url() in test_html) # Make sure that title and body text are escaped properly. # This should be obvious at this point, if the above test passes, but why not be explicit # UPDATE: And voila, these tests catched double-escaping bug in template, where `<` was `&lt;` # And indeed, post.summary is escaped before saving, in parse_and_save() # UPDATE 2:Weird things happen with question summary (it's double escaped etc., really weird) so # let's just make sure that there are no tag placeholders left self.assertTrue( '<<<tag1>>> fake title' in proper_html) #self.assertTrue('<<<tag2>>> <<<tag3>>> cheating' in proper_html) self.assertFalse('<<<tag1>>>' in proper_html) self.assertFalse('<<<tag2>>>' in proper_html) self.assertFalse('<<<tag3>>>' in proper_html) ### ss = ss.add_tag('mini-mini') context['search_state'] = ss test_html = thread.get_summary_html(search_state=ss) proper_html = get_template('widgets/question_summary.html').render( context) self.assertEqual(test_html, proper_html) # Make double-check that all tags are included (along with `mini-mini` tag) self.assertTrue(ss.add_tag('tag1').full_url() in test_html) self.assertTrue(ss.add_tag('tag2').full_url() in test_html) self.assertTrue(ss.add_tag('tag3').full_url() in test_html)
def get_question_body(request): search_state = request.session.get('search_state', SearchState()) view_log = request.session['view_log'] (qs, meta_data, related_tags) = models.Question.objects.run_advanced_search( request_user = request.user, search_state = search_state) paginator = Paginator(qs, search_state.page_size) page = paginator.page(search_state.page) questions_dict = {} for question in page.object_list: questions_dict['question-%s' % question.id] = question.summary return {'questions-titles': questions_dict} return {'questions-titles': questions_dict}
def test_run_adv_search_ANDing_tags(self): ss = SearchState.get_empty() qs, meta_data = Thread.objects.run_advanced_search(request_user=self.user, search_state=ss.add_tag('tag1')) self.assertEqual(2, qs.count()) qs, meta_data = Thread.objects.run_advanced_search(request_user=self.user, search_state=ss.add_tag('tag1').add_tag('tag3')) self.assertEqual(2, qs.count()) qs, meta_data = Thread.objects.run_advanced_search(request_user=self.user, search_state=ss.add_tag('tag1').add_tag('tag3').add_tag('tag6')) self.assertEqual(1, qs.count()) ss = SearchState(scope=None, sort=None, query="#tag3", tags='tag1, tag6', author=None, page=None, user_logged_in=None) qs, meta_data = Thread.objects.run_advanced_search(request_user=self.user, search_state=ss) self.assertEqual(1, qs.count())
def user(request, id, slug=None, tab_name=None): """Main user view function that works as a switchboard id - id of the profile owner todo: decide what to do with slug - it is not used in the code in any way """ profile_owner = get_object_or_404(models.User, id=id) if not tab_name: tab_name = request.GET.get('sort', 'stats') if askbot_settings.KARMA_MODE == 'public': can_show_karma = True elif askbot_settings.KARMA_MODE == 'hidden': can_show_karma = False else: if request.user.is_administrator_or_moderator() \ or request.user == profile_owner: can_show_karma = True else: can_show_karma = False if can_show_karma == False and tab_name == 'reputation': raise Http404 user_view_func = USER_VIEW_CALL_TABLE.get(tab_name, user_stats) search_state = SearchState( # Non-default SearchState with user data set scope=None, sort=None, query=None, tags=None, author=profile_owner.id, page=None, user_logged_in=profile_owner.is_authenticated(), ) context = { 'view_user': profile_owner, 'can_show_karma': can_show_karma, 'search_state': search_state, 'user_follow_feature_on': ('followit' in django_settings.INSTALLED_APPS), } if CUSTOM_TAB: context['custom_tab_name'] = CUSTOM_TAB['NAME'] context['custom_tab_slug'] = CUSTOM_TAB['SLUG'] return user_view_func(request, profile_owner, context)
def test_thread_caching_2_precache_view_data_hack(self): ss = SearchState.get_empty() qs, meta_data = Thread.objects.run_advanced_search(request_user=self.user, search_state=ss) qs = list(qs) Thread.objects.precache_view_data_hack(threads=qs) for thread in qs: post = Post.objects.get(post_type='question', thread=thread.id) self.assertEqual(post.id, thread._question_cache.id) # Cannot compare models instances with deferred model instances self.assertEqual(post.id, thread._question_post().id) self.assertTrue(thread._question_post() is thread._question_cache) user = User.objects.get(id=thread.last_activity_by_id) self.assertEqual(user.id, thread._last_activity_by_cache.id) self.assertTrue(thread.last_activity_by is thread._last_activity_by_cache)
def test_all_valid_selectors(self): ss = SearchState( scope="unanswered", sort="age-desc", query=" alfa", tags="miki, mini", author="12", page="2", user_logged_in=False, ) self.assertEqual( "scope:unanswered/sort:age-desc/query:alfa/tags:miki,mini/author:12/page:2/", ss.query_string() ) self.assertEqual( "scope:unanswered/sort:age-desc/query:alfa/tags:miki,mini/author:12/page:2/", ss.deepcopy().query_string() )
def test_thread_summary_rendering_dummy_cache(self): cache.cache = DummyCache('', {}) # Disable caching ss = SearchState.get_empty() thread = self.q.thread test_html = thread.get_summary_html(search_state=ss) context = { 'thread': thread, 'question': thread._question_post(), 'search_state': ss, 'visitor': None } proper_html = get_template('widgets/question_summary.html').render(context) self.assertEqual(test_html, proper_html) # Make double-check that all tags are included self.assertTrue(ss.add_tag('tag1').full_url() in test_html) self.assertTrue(ss.add_tag('tag2').full_url() in test_html) self.assertTrue(ss.add_tag('tag3').full_url() in test_html) self.assertFalse(ss.add_tag('mini-mini').full_url() in test_html) # Make sure that title and body text are escaped properly. # This should be obvious at this point, if the above test passes, but why not be explicit # UPDATE: And voila, these tests catched double-escaping bug in template, where `<` was `&lt;` # And indeed, post.summary is escaped before saving, in parse_and_save() # UPDATE 2:Weird things happen with question summary (it's double escaped etc., really weird) so # let's just make sure that there are no tag placeholders left self.assertTrue('<<<tag1>>> fake title' in proper_html) #self.assertTrue('<<<tag2>>> <<<tag3>>> cheating' in proper_html) self.assertFalse('<<<tag1>>>' in proper_html) self.assertFalse('<<<tag2>>>' in proper_html) self.assertFalse('<<<tag3>>>' in proper_html) ### ss = ss.add_tag('mini-mini') context['search_state'] = ss test_html = thread.get_summary_html(search_state=ss) proper_html = get_template('widgets/question_summary.html').render(context) self.assertEqual(test_html, proper_html) # Make double-check that all tags are included (along with `mini-mini` tag) self.assertTrue(ss.add_tag('tag1').full_url() in test_html) self.assertTrue(ss.add_tag('tag2').full_url() in test_html) self.assertTrue(ss.add_tag('tag3').full_url() in test_html)
def get_empty_search_state(unused): from askbot.search.state_manager import SearchState return SearchState.get_empty()
def questions(request, **kwargs): """ List of Questions, Tagged questions, and Unanswered questions. matching search query or user selection """ if request.method != 'GET': return HttpResponseNotAllowed(['GET']) search_state = SearchState(user_logged_in=request.user.is_authenticated(), **kwargs) ####### page_size = int(askbot_settings.DEFAULT_QUESTIONS_PAGE_SIZE) qs, meta_data, related_tags = models.Thread.objects.run_advanced_search(request_user=request.user, search_state=search_state, page_size=page_size) tag_list_type = askbot_settings.TAG_LIST_FORMAT if tag_list_type == 'cloud': #force cloud to sort by name related_tags = sorted(related_tags, key = operator.attrgetter('name')) paginator = Paginator(qs, page_size) if paginator.num_pages < search_state.page: search_state.page = 1 page = paginator.page(search_state.page) contributors_threads = models.Thread.objects.filter(id__in=[post.thread_id for post in page.object_list]) contributors = models.Thread.objects.get_thread_contributors(contributors_threads) paginator_context = { 'is_paginated' : (paginator.count > page_size), 'pages': paginator.num_pages, 'page': search_state.page, 'has_previous': page.has_previous(), 'has_next': page.has_next(), 'previous': page.previous_page_number(), 'next': page.next_page_number(), 'base_url' : search_state.query_string(),#todo in T sort=>sort_method 'page_size' : page_size,#todo in T pagesize -> page_size } # We need to pass the rss feed url based # on the search state to the template. # We use QueryDict to get a querystring # from dicts and arrays. Much cleaner # than parsing and string formating. rss_query_dict = QueryDict("").copy() if search_state.query: # We have search string in session - pass it to # the QueryDict rss_query_dict.update({"q": search_state.query}) if search_state.tags: # We have tags in session - pass it to the # QueryDict but as a list - we want tags+ rss_query_dict.setlist("tags", search_state.tags) context_feed_url = '/feeds/rss/?%s' % rss_query_dict.urlencode() # Format the url with the QueryDict reset_method_count = len(filter(None, [search_state.query, search_state.tags, meta_data.get('author_name', None)])) if request.is_ajax(): q_count = paginator.count if search_state.tags: question_counter = ungettext('%(q_num)s question, tagged', '%(q_num)s questions, tagged', q_count) else: question_counter = ungettext('%(q_num)s question', '%(q_num)s questions', q_count) question_counter = question_counter % {'q_num': humanize.intcomma(q_count),} if q_count > page_size: paginator_tpl = get_template('main_page/paginator.html', request) paginator_html = paginator_tpl.render(Context({ 'context': functions.setup_paginator(paginator_context), 'questions_count': q_count, 'page_size' : page_size, 'search_state': search_state, })) else: paginator_html = '' questions_tpl = get_template('main_page/questions_loop.html', request) questions_html = questions_tpl.render(Context({ 'questions': page, 'search_state': search_state, 'reset_method_count': reset_method_count, })) ajax_data = { 'query_data': { 'tags': search_state.tags, 'sort_order': search_state.sort, 'ask_query_string': search_state.ask_query_string(), }, 'paginator': paginator_html, 'question_counter': question_counter, 'questions': list(), 'faces': [extra_tags.gravatar(contributor, 48) for contributor in contributors], 'feed_url': context_feed_url, 'query_string': search_state.query_string(), 'page_size' : page_size, 'questions': questions_html.replace('\n',''), } ajax_data['related_tags'] = [{ 'name': tag.name, 'used_count': humanize.intcomma(tag.local_used_count) } for tag in related_tags] return HttpResponse(simplejson.dumps(ajax_data), mimetype = 'application/json') else: # non-AJAX branch template_data = { 'active_tab': 'questions', 'author_name' : meta_data.get('author_name',None), 'contributors' : contributors, 'context' : paginator_context, '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), 'language_code': translation.get_language(), 'name_of_anonymous_user' : models.get_name_of_anonymous_user(), 'page_class': 'main-page', 'page_size': page_size, 'query': search_state.query, 'questions' : page, 'questions_count' : paginator.count, 'reset_method_count': reset_method_count, 'scope': search_state.scope, 'show_sort_by_relevance': askbot.conf.should_show_sort_by_relevance(), 'search_tags' : search_state.tags, 'sort': search_state.sort, 'tab_id' : search_state.sort, 'tags' : related_tags, 'tag_list_type' : tag_list_type, 'font_size' : extra_tags.get_tag_font_size(related_tags), 'tag_filter_strategy_choices': const.TAG_FILTER_STRATEGY_CHOICES, 'update_avatar_data': schedules.should_update_avatar_data(request), 'query_string': search_state.query_string(), 'search_state': search_state, 'feed_url': context_feed_url, } return render_into_skin('main_page.html', template_data, request)
def questions(request, **kwargs): """ List of Questions, Tagged questions, and Unanswered questions. matching search query or user selection """ #before = datetime.datetime.now() if request.method != 'GET': return HttpResponseNotAllowed(['GET']) search_state = SearchState( user_logged_in=request.user.is_authenticated(), **kwargs ) page_size = int(askbot_settings.DEFAULT_QUESTIONS_PAGE_SIZE) qs, meta_data = models.Thread.objects.run_advanced_search( request_user=request.user, search_state=search_state ) current_lang = request.session['django_language'] langs = settings.ASKBOT_LANG_TAGS.copy() if current_lang in langs: langs.pop(current_lang) if current_lang == 'en': qs = qs.exclude(tags__name__in=langs) else: qs = qs.filter(tags__name=current_lang) if meta_data['non_existing_tags']: search_state = search_state.remove_tags(meta_data['non_existing_tags']) paginator = Paginator(qs, page_size) if paginator.num_pages < search_state.page: search_state.page = 1 page = paginator.page(search_state.page) page.object_list = list(page.object_list) # evaluate the queryset # INFO: Because for the time being we need question posts and thread authors # down the pipeline, we have to precache them in thread objects models.Thread.objects.precache_view_data_hack(threads=page.object_list) related_tags = Tag.objects.get_related_to_search( threads=page.object_list, ignored_tag_names=meta_data.get('ignored_tag_names',[]) ) tag_list_type = askbot_settings.TAG_LIST_FORMAT if tag_list_type == 'cloud': #force cloud to sort by name related_tags = sorted(related_tags, key = operator.attrgetter('name')) contributors = list( models.Thread.objects.get_thread_contributors( thread_list=page.object_list ).only('id', 'username', 'gravatar') ) paginator_context = { 'is_paginated' : (paginator.count > page_size), 'pages': paginator.num_pages, 'page': search_state.page, 'has_previous': page.has_previous(), 'has_next': page.has_next(), 'previous': page.previous_page_number(), 'next': page.next_page_number(), 'base_url' : search_state.query_string(), 'page_size' : page_size, } # We need to pass the rss feed url based # on the search state to the template. # We use QueryDict to get a querystring # from dicts and arrays. Much cleaner # than parsing and string formating. rss_query_dict = QueryDict("").copy() if search_state.query: # We have search string in session - pass it to # the QueryDict rss_query_dict.update({"q": search_state.query}) if search_state.tags: # We have tags in session - pass it to the # QueryDict but as a list - we want tags+ rss_query_dict.setlist("tags", search_state.tags) context_feed_url = '/%sfeeds/rss/?%s' % (settings.ASKBOT_URL, rss_query_dict.urlencode()) # Format the url with the QueryDict reset_method_count = len(filter(None, [search_state.query, search_state.tags, meta_data.get('author_name', None)])) if request.is_ajax(): q_count = paginator.count question_counter = ungettext('%(q_num)s question', '%(q_num)s questions', q_count) question_counter = question_counter % {'q_num': humanize.intcomma(q_count),} if q_count > page_size: paginator_tpl = get_template('main_page/paginator.html') paginator_html = paginator_tpl.render( RequestContext( request, { 'context': functions.setup_paginator(paginator_context), 'questions_count': q_count, 'page_size' : page_size, 'search_state': search_state, } ) ) else: paginator_html = '' questions_tpl = get_template('main_page/questions_loop.html') questions_html = questions_tpl.render( RequestContext( request, { 'threads': page, 'search_state': search_state, 'reset_method_count': reset_method_count, 'request': request } ) ) ajax_data = { 'query_data': { 'tags': search_state.tags, 'sort_order': search_state.sort, 'ask_query_string': search_state.ask_query_string(), }, 'paginator': paginator_html, 'question_counter': question_counter, 'faces': [],#[extra_tags.gravatar(contributor, 48) for contributor in contributors], 'feed_url': context_feed_url, 'query_string': search_state.query_string(), 'page_size' : page_size, 'questions': questions_html.replace('\n',''), 'non_existing_tags': meta_data['non_existing_tags'] } ajax_data['related_tags'] = [{ 'name': escape(tag.name), 'used_count': humanize.intcomma(tag.local_used_count) } for tag in related_tags] return HttpResponse(simplejson.dumps(ajax_data), mimetype = 'application/json') else: # non-AJAX branch template_data = { 'active_tab': 'questions', 'author_name' : meta_data.get('author_name',None), 'contributors' : contributors, 'context' : paginator_context, '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), 'subscribed_tag_names': meta_data.get('subscribed_tag_names', None), 'language_code': translation.get_language(), 'name_of_anonymous_user' : models.get_name_of_anonymous_user(), 'page_class': 'main-page', 'page_size': page_size, 'query': search_state.query, 'threads' : page, 'questions_count' : paginator.count, 'reset_method_count': reset_method_count, 'scope': search_state.scope, 'show_sort_by_relevance': conf.should_show_sort_by_relevance(), 'search_tags' : search_state.tags, 'sort': search_state.sort, 'tab_id' : search_state.sort, 'tags' : related_tags, 'tag_list_type' : tag_list_type, 'font_size' : extra_tags.get_tag_font_size(related_tags), 'display_tag_filter_strategy_choices': conf.get_tag_display_filter_strategy_choices(), 'email_tag_filter_strategy_choices': const.TAG_EMAIL_FILTER_STRATEGY_CHOICES, 'update_avatar_data': schedules.should_update_avatar_data(request), 'query_string': search_state.query_string(), 'search_state': search_state, 'feed_url': context_feed_url, 'lang_tags': settings.ASKBOT_LANG_TAGS, } return render(request, 'main_page.html', template_data)
def test_run_adv_search_1(self): ss = SearchState.get_empty() qs, meta_data = Thread.objects.run_advanced_search(request_user=self.user, search_state=ss) self.assertEqual(4, qs.count())
def proto_test_non_user_urls(self, status_code): """test all reader views thoroughly on non-crashiness (no correcteness tests here) """ self.try_url('sitemap') self.try_url('get_groups_list', status_code=status_code) #self.try_url( # 'individual_question_feed', # kwargs={'pk':'one-tag'}, # status_code=status_code) self.try_url('latest_questions_feed', status_code=status_code) self.try_url('latest_questions_feed', data={'tags': 'one-tag'}, status_code=status_code) self.try_url('about', status_code=status_code, template='static_page.html') self.try_url('privacy', status_code=status_code, template='static_page.html') self.try_url('logout', template='authopenid/logout.html') #todo: test different tabs self.try_url('tags', status_code=status_code, template='tags.html') self.try_url('tags', status_code=status_code, data={'sort': 'name'}, template='tags.html') self.try_url('tags', status_code=status_code, data={'sort': 'used'}, template='tags.html') self.try_url('badges', status_code=status_code, template='badges.html') self.try_url('answer_revisions', status_code=status_code, template='revisions.html', kwargs={ 'id': models.Post.objects.get_answers().order_by('id')[0].id }) #todo: test different sort methods and scopes self.try_url('questions', status_code=status_code, template='main_page.html') self.try_url( url_name=reverse('questions') + SearchState.get_empty().change_scope('unanswered').query_string(), plain_url_passed=True, status_code=status_code, template='main_page.html', ) self.try_url( url_name=reverse('questions') + SearchState.get_empty().change_scope('favorite').query_string(), plain_url_passed=True, status_code=status_code, template='main_page.html') self.try_url(url_name=reverse('questions') + SearchState.get_empty().change_scope( 'unanswered').change_sort('age-desc').query_string(), plain_url_passed=True, status_code=status_code, template='main_page.html') self.try_url(url_name=reverse('questions') + SearchState.get_empty().change_scope( 'unanswered').change_sort('age-asc').query_string(), plain_url_passed=True, status_code=status_code, template='main_page.html') self.try_url( url_name=reverse('questions') + SearchState.get_empty().change_scope('unanswered').change_sort( 'activity-desc').query_string(), plain_url_passed=True, status_code=status_code, template='main_page.html') self.try_url( url_name=reverse('questions') + SearchState.get_empty().change_scope('unanswered').change_sort( 'activity-asc').query_string(), plain_url_passed=True, status_code=status_code, template='main_page.html') self.try_url( url_name=reverse('questions') + SearchState.get_empty().change_sort('answers-desc').query_string(), plain_url_passed=True, status_code=status_code, template='main_page.html') self.try_url( url_name=reverse('questions') + SearchState.get_empty().change_sort('answers-asc').query_string(), plain_url_passed=True, status_code=status_code, template='main_page.html') self.try_url( url_name=reverse('questions') + SearchState.get_empty().change_sort('votes-desc').query_string(), plain_url_passed=True, status_code=status_code, template='main_page.html') self.try_url( url_name=reverse('questions') + SearchState.get_empty().change_sort('votes-asc').query_string(), plain_url_passed=True, status_code=status_code, template='main_page.html') self.try_url( 'question', status_code=status_code, kwargs={ 'id': 1 }, # INFO: Hardcoded ID, might fail if DB allocates IDs in some non-continuous way follow=True, template='question.html') self.try_url( 'question', status_code=status_code, kwargs={ 'id': 2 }, # INFO: Hardcoded ID, might fail if DB allocates IDs in some non-continuous way follow=True, template='question.html') self.try_url( 'question', status_code=status_code, kwargs={ 'id': 3 }, # INFO: Hardcoded ID, might fail if DB allocates IDs in some non-continuous way follow=True, template='question.html') self.try_url( 'question_revisions', status_code=status_code, kwargs={ 'id': 40 }, # INFO: Hardcoded ID, might fail if DB allocates IDs in some non-continuous way template='revisions.html') self.try_url('users', status_code=status_code, template='users.html') #self.try_url( # 'widget_questions', # status_code = status_code, # data={'tags': 'tag-1-0'}, # template='question_widget.html', # ) #todo: really odd naming conventions for sort methods self.try_url( 'users', status_code=status_code, template='users.html', data={'sort': 'reputation'}, ) self.try_url( 'users', status_code=status_code, template='users.html', data={'sort': 'newest'}, ) self.try_url( 'users', status_code=status_code, template='users.html', data={'sort': 'last'}, ) self.try_url( 'users', status_code=status_code, template='users.html', data={'sort': 'user'}, ) self.try_url( 'users', status_code=status_code, template='users.html', data={ 'sort': 'reputation', 'page': 2 }, ) self.try_url( 'users', status_code=status_code, template='users.html', data={ 'sort': 'newest', 'page': 2 }, ) self.try_url( 'users', status_code=status_code, template='users.html', data={ 'sort': 'last', 'page': 2 }, ) self.try_url( 'users', status_code=status_code, template='users.html', data={ 'sort': 'user', 'page': 2 }, ) self.try_url( 'users', status_code=status_code, template='users.html', data={ 'sort': 'reputation', 'page': 1 }, ) self.try_url( 'users', status_code=status_code, template='users.html', data={ 'sort': 'newest', 'page': 1 }, ) self.try_url( 'users', status_code=status_code, template='users.html', data={ 'sort': 'last', 'page': 1 }, ) self.try_url( 'users', status_code=status_code, template='users.html', data={ 'sort': 'user', 'page': 1 }, ) self.try_url( 'edit_user', template='authopenid/signin.html', kwargs={ 'id': 4 }, # INFO: Hardcoded ID, might fail if DB allocates IDs in some non-continuous way status_code=status_code, follow=True, ) self.try_url( 'faq', template='faq_static.html', status_code=status_code, )
def proto_test_non_user_urls(self, status_code): """test all reader views thoroughly on non-crashiness (no correcteness tests here) """ self.try_url('sitemap') self.try_url( 'feeds', status_code=status_code, kwargs={'url':'rss'}) self.try_url( 'feeds', kwargs={'url':'rss'}, data={'tags':'one-tag'}, status_code=status_code) #self.try_url( # 'feeds', # kwargs={'url':'question'}, # status_code=status_code) self.try_url( 'about', status_code=status_code, template='static_page.html') self.try_url( 'privacy', status_code=status_code, template='static_page.html') self.try_url('logout', template='authopenid/logout.html') #todo: test different tabs self.try_url( 'tags', status_code=status_code, template='tags.html') self.try_url( 'tags', status_code=status_code, data={'sort':'name'}, template='tags.html') self.try_url( 'tags', status_code=status_code, data={'sort':'used'}, template='tags.html') self.try_url( 'badges', status_code=status_code, template='badges.html') self.try_url( 'answer_revisions', status_code=status_code, template='revisions.html', kwargs={'id': models.Post.objects.get_answers().order_by('id')[0].id} ) #todo: test different sort methods and scopes self.try_url( 'questions', status_code=status_code, template='main_page.html' ) self.try_url( url_name=reverse('questions') + SearchState.get_empty().change_scope('unanswered').query_string(), plain_url_passed=True, status_code=status_code, template='main_page.html', ) self.try_url( url_name=reverse('questions') + SearchState.get_empty().change_scope('favorite').query_string(), plain_url_passed=True, status_code=status_code, template='main_page.html' ) self.try_url( url_name=reverse('questions') + SearchState.get_empty().change_scope('unanswered').change_sort('age-desc').query_string(), plain_url_passed=True, status_code=status_code, template='main_page.html' ) self.try_url( url_name=reverse('questions') + SearchState.get_empty().change_scope('unanswered').change_sort('age-asc').query_string(), plain_url_passed=True, status_code=status_code, template='main_page.html' ) self.try_url( url_name=reverse('questions') + SearchState.get_empty().change_scope('unanswered').change_sort('activity-desc').query_string(), plain_url_passed=True, status_code=status_code, template='main_page.html' ) self.try_url( url_name=reverse('questions') + SearchState.get_empty().change_scope('unanswered').change_sort('activity-asc').query_string(), plain_url_passed=True, status_code=status_code, template='main_page.html' ) self.try_url( url_name=reverse('questions') + SearchState.get_empty().change_sort('answers-desc').query_string(), plain_url_passed=True, status_code=status_code, template='main_page.html' ) self.try_url( url_name=reverse('questions') + SearchState.get_empty().change_sort('answers-asc').query_string(), plain_url_passed=True, status_code=status_code, template='main_page.html' ) self.try_url( url_name=reverse('questions') + SearchState.get_empty().change_sort('votes-desc').query_string(), plain_url_passed=True, status_code=status_code, template='main_page.html' ) self.try_url( url_name=reverse('questions') + SearchState.get_empty().change_sort('votes-asc').query_string(), plain_url_passed=True, status_code=status_code, template='main_page.html' ) self.try_url( 'question', status_code=status_code, kwargs={'id':1}, # INFO: Hardcoded ID, might fail if DB allocates IDs in some non-continuous way follow=True, template='question.html' ) self.try_url( 'question', status_code=status_code, kwargs={'id':2}, # INFO: Hardcoded ID, might fail if DB allocates IDs in some non-continuous way follow=True, template='question.html' ) self.try_url( 'question', status_code=status_code, kwargs={'id':3}, # INFO: Hardcoded ID, might fail if DB allocates IDs in some non-continuous way follow=True, template='question.html' ) self.try_url( 'question_revisions', status_code=status_code, kwargs={'id':40}, # INFO: Hardcoded ID, might fail if DB allocates IDs in some non-continuous way template='revisions.html' ) self.try_url('users', status_code=status_code, template='users.html' ) self.try_url( 'widget_questions', status_code = status_code, data={'tags': 'tag-1-0'}, template='question_widget.html', ) #todo: really odd naming conventions for sort methods self.try_url( 'users', status_code=status_code, template='users.html', data={'sort':'reputation'}, ) self.try_url( 'users', status_code=status_code, template='users.html', data={'sort':'newest'}, ) self.try_url( 'users', status_code=status_code, template='users.html', data={'sort':'last'}, ) self.try_url( 'users', status_code=status_code, template='users.html', data={'sort':'user'}, ) self.try_url( 'users', status_code=status_code, template='users.html', data={'sort':'reputation', 'page':2}, ) self.try_url( 'users', status_code=status_code, template='users.html', data={'sort':'newest', 'page':2}, ) self.try_url( 'users', status_code=status_code, template='users.html', data={'sort':'last', 'page':2}, ) self.try_url( 'users', status_code=status_code, template='users.html', data={'sort':'user', 'page':2}, ) self.try_url( 'users', status_code=status_code, template='users.html', data={'sort':'reputation', 'page':1}, ) self.try_url( 'users', status_code=status_code, template='users.html', data={'sort':'newest', 'page':1}, ) self.try_url( 'users', status_code=status_code, template='users.html', data={'sort':'last', 'page':1}, ) self.try_url( 'users', status_code=status_code, template='users.html', data={'sort':'user', 'page':1}, ) self.try_url( 'edit_user', template='authopenid/signin.html', kwargs={'id':4}, # INFO: Hardcoded ID, might fail if DB allocates IDs in some non-continuous way status_code=status_code, follow=True, ) self.try_url( 'faq', template='faq_static.html', status_code=status_code, )
def questions(request, **kwargs): """ List of Questions, Tagged questions, and Unanswered questions. matching search query or user selection """ #before = datetime.datetime.now() if request.method != 'GET': return HttpResponseNotAllowed(['GET']) search_state = SearchState( user_logged_in=request.user.is_authenticated(), **kwargs ) qs, meta_data = models.Thread.objects.run_advanced_search( request_user=request.user, search_state=search_state ) if meta_data['non_existing_tags']: search_state = search_state.remove_tags(meta_data['non_existing_tags']) paginator = Paginator(qs, search_state.page_size) if paginator.num_pages < search_state.page: search_state.page = 1 page = paginator.page(search_state.page) page.object_list = list(page.object_list) # evaluate the queryset # INFO: Because for the time being we need question posts and thread authors # down the pipeline, we have to precache them in thread objects models.Thread.objects.precache_view_data_hack(threads=page.object_list) related_tags = Tag.objects.get_related_to_search( threads=page.object_list, ignored_tag_names=meta_data.get('ignored_tag_names',[]) ) tag_list_type = askbot_settings.TAG_LIST_FORMAT if tag_list_type == 'cloud': #force cloud to sort by name related_tags = sorted(related_tags, key = operator.attrgetter('name')) contributors = list( models.Thread.objects.get_thread_contributors( thread_list=page.object_list ).only('id', 'username', 'gravatar') ) paginator_context = { 'is_paginated' : (paginator.count > search_state.page_size), 'pages': paginator.num_pages, 'current_page_number': search_state.page, 'page_object': page, 'base_url' : search_state.query_string(), 'page_size' : search_state.page_size, } #get url for the rss feed context_feed_url = reverse('latest_questions_feed') # We need to pass the rss feed url based # on the search state to the template. # We use QueryDict to get a querystring # from dicts and arrays. Much cleaner # than parsing and string formating. rss_query_dict = QueryDict("").copy() if search_state.query: # We have search string in session - pass it to # the QueryDict rss_query_dict.update({"q": search_state.query}) if search_state.tags: # We have tags in session - pass it to the # QueryDict but as a list - we want tags+ rss_query_dict.setlist('tags', search_state.tags) context_feed_url += '?' + rss_query_dict.urlencode() reset_method_count = len(filter(None, [search_state.query, search_state.tags, meta_data.get('author_name', None)])) if request.is_ajax(): q_count = paginator.count #todo: words question_counter = ungettext('%(q_num)s question', '%(q_num)s questions', q_count) question_counter = question_counter % {'q_num': humanize.intcomma(q_count),} if q_count > search_state.page_size: paginator_tpl = get_template('main_page/paginator.html') paginator_html = paginator_tpl.render( RequestContext( request, { 'context': paginator_context, 'questions_count': q_count, 'page_size' : search_state.page_size, 'search_state': search_state, } ) ) else: paginator_html = '' questions_tpl = get_template('main_page/questions_loop.html') questions_html = questions_tpl.render( RequestContext( request, { 'threads': page, 'search_state': search_state, 'reset_method_count': reset_method_count, 'request': request } ) ) ajax_data = { 'query_data': { 'tags': search_state.tags, 'sort_order': search_state.sort, 'ask_query_string': search_state.ask_query_string(), }, 'paginator': paginator_html, 'question_counter': question_counter, 'faces': [],#[extra_tags.gravatar(contributor, 48) for contributor in contributors], 'feed_url': context_feed_url, 'query_string': search_state.query_string(), 'page_size' : search_state.page_size, 'questions': questions_html.replace('\n',''), 'non_existing_tags': meta_data['non_existing_tags'], } related_tags_tpl = get_template('widgets/related_tags.html') related_tags_data = { 'tags': related_tags, 'tag_list_type': tag_list_type, 'query_string': search_state.query_string(), 'search_state': search_state, 'language_code': translation.get_language(), } if tag_list_type == 'cloud': related_tags_data['font_size'] = extra_tags.get_tag_font_size(related_tags) ajax_data['related_tags_html'] = related_tags_tpl.render( RequestContext(request, related_tags_data) ) #here we add and then delete some items #to allow extra context processor to work ajax_data['tags'] = related_tags ajax_data['interesting_tag_names'] = None ajax_data['threads'] = page extra_context = context.get_extra( 'ASKBOT_QUESTIONS_PAGE_EXTRA_CONTEXT', request, ajax_data ) del ajax_data['tags'] del ajax_data['interesting_tag_names'] del ajax_data['threads'] ajax_data.update(extra_context) return HttpResponse(simplejson.dumps(ajax_data), mimetype = 'application/json') else: # non-AJAX branch template_data = { 'active_tab': 'questions', 'author_name' : meta_data.get('author_name',None), 'contributors' : contributors, 'context' : paginator_context, '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), 'subscribed_tag_names': meta_data.get('subscribed_tag_names', None), 'language_code': translation.get_language(), 'name_of_anonymous_user' : models.get_name_of_anonymous_user(), 'page_class': 'main-page', 'page_size': search_state.page_size, 'query': search_state.query, 'threads' : page, 'questions_count' : paginator.count, 'reset_method_count': reset_method_count, 'scope': search_state.scope, 'show_sort_by_relevance': conf.should_show_sort_by_relevance(), 'search_tags' : search_state.tags, 'sort': search_state.sort, 'tab_id' : search_state.sort, 'tags' : related_tags, 'tag_list_type' : tag_list_type, 'font_size' : extra_tags.get_tag_font_size(related_tags), 'display_tag_filter_strategy_choices': conf.get_tag_display_filter_strategy_choices(), 'email_tag_filter_strategy_choices': conf.get_tag_email_filter_strategy_choices(), 'query_string': search_state.query_string(), 'search_state': search_state, 'feed_url': context_feed_url } extra_context = context.get_extra( 'ASKBOT_QUESTIONS_PAGE_EXTRA_CONTEXT', request, template_data ) template_data.update(extra_context) template_data.update(context.get_for_tag_editor()) #and one more thing:) give admin user heads up about #setting the domain name if they have not done that yet #todo: move this out to a separate middleware if request.user.is_authenticated() and request.user.is_administrator(): if domain_is_bad(): url = askbot_settings.get_setting_url(('QA_SITE_SETTINGS', 'APP_URL')) msg = _( 'Please go to Settings -> %s ' 'and set the base url for your site to function properly' ) % url request.user.message_set.create(message=msg) return render(request, 'main_page.html', template_data)
def test_run_adv_search_1(self): ss = SearchState.get_empty() qs, meta_data = Thread.objects.run_advanced_search( request_user=self.user, search_state=ss) self.assertEqual(4, qs.count())
def test_cannot_add_already_added_tag(self): ss = SearchState.get_empty().add_tag('double').add_tag('double') self.assertListEqual(['double'], ss.tags)
def proto_test_non_user_urls(self, status_code): """test all reader views thoroughly on non-crashiness (no correcteness tests here) """ self.try_url("sitemap") self.try_url("get_groups_list", status_code=status_code) # self.try_url( # 'individual_question_feed', # kwargs={'pk':'one-tag'}, # status_code=status_code) self.try_url("latest_questions_feed", status_code=status_code) self.try_url("latest_questions_feed", data={"tags": "one-tag"}, status_code=status_code) self.try_url("about", status_code=status_code, template="static_page.html") self.try_url("privacy", status_code=status_code, template="static_page.html") self.try_url("logout", template="authopenid/logout.html") # todo: test different tabs self.try_url("tags", status_code=status_code, template="tags.html") self.try_url("tags", status_code=status_code, data={"sort": "name"}, template="tags.html") self.try_url("tags", status_code=status_code, data={"sort": "used"}, template="tags.html") self.try_url("badges", status_code=status_code, template="badges.html") self.try_url( "answer_revisions", status_code=status_code, template="revisions.html", kwargs={"id": models.Post.objects.get_answers().order_by("id")[0].id}, ) # todo: test different sort methods and scopes self.try_url("questions", status_code=status_code, template="main_page.html") self.try_url( url_name=reverse("questions") + SearchState.get_empty().change_scope("unanswered").query_string(), plain_url_passed=True, status_code=status_code, template="main_page.html", ) self.try_url( url_name=reverse("questions") + SearchState.get_empty().change_scope("followed").query_string(), plain_url_passed=True, status_code=status_code, template="main_page.html", ) self.try_url( url_name=reverse("questions") + SearchState.get_empty().change_scope("unanswered").change_sort("age-desc").query_string(), plain_url_passed=True, status_code=status_code, template="main_page.html", ) self.try_url( url_name=reverse("questions") + SearchState.get_empty().change_scope("unanswered").change_sort("age-asc").query_string(), plain_url_passed=True, status_code=status_code, template="main_page.html", ) self.try_url( url_name=reverse("questions") + SearchState.get_empty().change_scope("unanswered").change_sort("activity-desc").query_string(), plain_url_passed=True, status_code=status_code, template="main_page.html", ) self.try_url( url_name=reverse("questions") + SearchState.get_empty().change_scope("unanswered").change_sort("activity-asc").query_string(), plain_url_passed=True, status_code=status_code, template="main_page.html", ) self.try_url( url_name=reverse("questions") + SearchState.get_empty().change_sort("answers-desc").query_string(), plain_url_passed=True, status_code=status_code, template="main_page.html", ) self.try_url( url_name=reverse("questions") + SearchState.get_empty().change_sort("answers-asc").query_string(), plain_url_passed=True, status_code=status_code, template="main_page.html", ) self.try_url( url_name=reverse("questions") + SearchState.get_empty().change_sort("votes-desc").query_string(), plain_url_passed=True, status_code=status_code, template="main_page.html", ) self.try_url( url_name=reverse("questions") + SearchState.get_empty().change_sort("votes-asc").query_string(), plain_url_passed=True, status_code=status_code, template="main_page.html", ) self.try_url( "question", status_code=status_code, kwargs={"id": 1}, # INFO: Hardcoded ID, might fail if DB allocates IDs in some non-continuous way follow=True, template="question.html", ) self.try_url( "question", status_code=status_code, kwargs={"id": 2}, # INFO: Hardcoded ID, might fail if DB allocates IDs in some non-continuous way follow=True, template="question.html", ) self.try_url( "question", status_code=status_code, kwargs={"id": 3}, # INFO: Hardcoded ID, might fail if DB allocates IDs in some non-continuous way follow=True, template="question.html", ) self.try_url( "question_revisions", status_code=status_code, kwargs={"id": 40}, # INFO: Hardcoded ID, might fail if DB allocates IDs in some non-continuous way template="revisions.html", ) self.try_url("users", status_code=status_code, template="users.html") # self.try_url( # 'widget_questions', # status_code = status_code, # data={'tags': 'tag-1-0'}, # template='question_widget.html', # ) # todo: really odd naming conventions for sort methods self.try_url("users", status_code=status_code, template="users.html", data={"sort": "reputation"}) self.try_url("users", status_code=status_code, template="users.html", data={"sort": "newest"}) self.try_url("users", status_code=status_code, template="users.html", data={"sort": "last"}) self.try_url("users", status_code=status_code, template="users.html", data={"sort": "user"}) self.try_url("users", status_code=status_code, template="users.html", data={"sort": "reputation", "page": 2}) self.try_url("users", status_code=status_code, template="users.html", data={"sort": "newest", "page": 2}) self.try_url("users", status_code=status_code, template="users.html", data={"sort": "last", "page": 2}) self.try_url("users", status_code=status_code, template="users.html", data={"sort": "user", "page": 2}) self.try_url("users", status_code=status_code, template="users.html", data={"sort": "reputation", "page": 1}) self.try_url("users", status_code=status_code, template="users.html", data={"sort": "newest", "page": 1}) self.try_url("users", status_code=status_code, template="users.html", data={"sort": "last", "page": 1}) self.try_url("users", status_code=status_code, template="users.html", data={"sort": "user", "page": 1}) self.try_url( "edit_user", template="authopenid/signin.html", kwargs={"id": 4}, # INFO: Hardcoded ID, might fail if DB allocates IDs in some non-continuous way status_code=status_code, follow=True, ) self.try_url("faq", template="faq_static.html", status_code=status_code)
def application_settings(request): """The context processor function""" if not request.path.startswith('/' + settings.ASKBOT_URL): #todo: this is a really ugly hack, will only work #when askbot is installed not at the home page. #this will not work for the #heavy modders of askbot, because their custom pages #will not receive the askbot settings in the context #to solve this properly we should probably explicitly #add settings to the context per page return {} my_settings = askbot_settings.as_dict() my_settings['LANGUAGE_CODE'] = getattr(request, 'LANGUAGE_CODE', settings.LANGUAGE_CODE) my_settings['MULTILINGUAL'] = getattr(settings, 'ASKBOT_MULTILINGUAL', False) my_settings['LANGUAGES_DICT'] = dict(getattr(settings, 'LANGUAGES', [])) my_settings['ALLOWED_UPLOAD_FILE_TYPES'] = \ settings.ASKBOT_ALLOWED_UPLOAD_FILE_TYPES my_settings['ASKBOT_URL'] = settings.ASKBOT_URL my_settings['STATIC_URL'] = settings.STATIC_URL my_settings['IP_MODERATION_ENABLED'] = getattr(settings, 'ASKBOT_IP_MODERATION_ENABLED', False) my_settings['ASKBOT_CSS_DEVEL'] = getattr( settings, 'ASKBOT_CSS_DEVEL', False ) my_settings['USE_LOCAL_FONTS'] = getattr( settings, 'ASKBOT_USE_LOCAL_FONTS', False ) my_settings['CSRF_COOKIE_NAME'] = settings.CSRF_COOKIE_NAME my_settings['DEBUG'] = settings.DEBUG my_settings['USING_RUNSERVER'] = 'runserver' in sys.argv my_settings['ASKBOT_VERSION'] = askbot.get_version() my_settings['LOGIN_URL'] = url_utils.get_login_url() my_settings['LOGOUT_URL'] = url_utils.get_logout_url() if my_settings['EDITOR_TYPE'] == 'tinymce': tinymce_plugins = settings.TINYMCE_DEFAULT_CONFIG.get('plugins', '').split(',') my_settings['TINYMCE_PLUGINS'] = map(lambda v: v.strip(), tinymce_plugins) else: my_settings['TINYMCE_PLUGINS'] = []; my_settings['LOGOUT_REDIRECT_URL'] = url_utils.get_logout_redirect_url() my_settings['USE_ASKBOT_LOGIN_SYSTEM'] = 'askbot.deps.django_authopenid' \ in settings.INSTALLED_APPS current_language = get_language() #for some languages we will start searching for shorter words if current_language == 'ja': #we need to open the search box and show info message about #the japanese lang search min_search_word_length = 1 else: min_search_word_length = my_settings['MIN_SEARCH_WORD_LENGTH'] need_scope_links = askbot_settings.ALL_SCOPE_ENABLED or \ askbot_settings.UNANSWERED_SCOPE_ENABLED or \ (request.user.is_authenticated() and askbot_settings.FOLLOWED_SCOPE_ENABLED) context = { 'base_url': site_url(''), 'empty_search_state': SearchState.get_empty(), 'min_search_word_length': min_search_word_length, 'current_language_code': current_language, 'settings': my_settings, 'skin': get_skin(), 'moderation_items': api.get_info_on_moderation_items(request.user), 'need_scope_links': need_scope_links, 'noscript_url': const.DEPENDENCY_URLS['noscript'], } if askbot_settings.GROUPS_ENABLED: #calculate context needed to list all the groups def _get_group_url(group): """calculates url to the group based on its id and name""" group_slug = slugify(group['name']) return reverse( 'users_by_group', kwargs={'group_id': group['id'], 'group_slug': group_slug} ) #load id's and names of all groups global_group = models.Group.objects.get_global_group() groups = models.Group.objects.exclude_personal() groups = groups.exclude(id=global_group.id) groups_data = list(groups.values('id', 'name')) #sort groups_data alphanumerically, but case-insensitive groups_data = sorted( groups_data, lambda x, y: cmp(x['name'].lower(), y['name'].lower()) ) #insert data for the global group at the first position groups_data.insert(0, {'id': global_group.id, 'name': global_group.name}) #build group_list for the context group_list = list() for group in groups_data: link = _get_group_url(group) group_list.append({'name': group['name'], 'link': link}) context['group_list'] = simplejson.dumps(group_list) return context
def tags(request):#view showing a listing of available tags - plain list form = ShowTagsForm(request.REQUEST) form.full_clean() #always valid page = form.cleaned_data['page'] sort_method = form.cleaned_data['sort'] query = form.cleaned_data['query'] tag_list_type = askbot_settings.TAG_LIST_FORMAT #2) Get query set for the tags. query_params = { 'deleted': False, 'language_code': translation.get_language() } if query != '': query_params['name__icontains'] = query tags_qs = Tag.objects.filter(**query_params).exclude(used_count=0) if sort_method == 'name': order_by = 'name' else: order_by = '-used_count' tags_qs = tags_qs.order_by(order_by) #3) Start populating the template context. data = { 'active_tab': 'tags', 'page_class': 'tags-page', 'tag_list_type' : tag_list_type, 'query' : query, 'tab_id' : sort_method, 'keywords' : query, 'search_state': SearchState(*[None for x in range(8)]) } if tag_list_type == 'list': #plain listing is paginated objects_list = Paginator(tags_qs, const.TAGS_PAGE_SIZE) try: tags = objects_list.page(page) except (EmptyPage, InvalidPage): tags = objects_list.page(objects_list.num_pages) paginator_data = { 'is_paginated' : (objects_list.num_pages > 1), 'pages': objects_list.num_pages, 'current_page_number': page, 'page_object': tags, 'base_url' : reverse('tags') + '?sort=%s&' % sort_method } paginator_context = functions.setup_paginator(paginator_data) data['paginator_context'] = paginator_context else: #tags for the tag cloud are given without pagination tags = tags_qs font_size = extra_tags.get_tag_font_size(tags) data['font_size'] = font_size data['tags'] = tags data.update(context.get_extra('ASKBOT_TAGS_PAGE_EXTRA_CONTEXT', request, data)) if request.is_ajax(): template = get_template('tags/content.html') template_context = RequestContext(request, data) json_data = {'success': True, 'html': template.render(template_context)} json_string = simplejson.dumps(json_data) return HttpResponse(json_string, content_type='application/json') else: return render(request, 'tags.html', data)
def questions(request, **kwargs): """ List of Questions, Tagged questions, and Unanswered questions. matching search query or user selection """ if request.method != 'GET': return HttpResponseNotAllowed(['GET']) search_state = SearchState(user_logged_in=request.user.is_authenticated(), **kwargs) page_size = int(askbot_settings.DEFAULT_QUESTIONS_PAGE_SIZE) qs, meta_data = models.Thread.objects.run_advanced_search( request_user=request.user, search_state=search_state) if meta_data['non_existing_tags']: search_state = search_state.remove_tags(meta_data['non_existing_tags']) paginator = Paginator(qs, page_size) if paginator.num_pages < search_state.page: search_state.page = 1 page = paginator.page(search_state.page) page.object_list = list(page.object_list) # evaluate queryset # INFO: Because for the time being we need question posts and thread authors # down the pipeline, we have to precache them in thread objects models.Thread.objects.precache_view_data_hack(threads=page.object_list) related_tags = Tag.objects.get_related_to_search( threads=page.object_list, ignored_tag_names=meta_data.get('ignored_tag_names', [])) tag_list_type = askbot_settings.TAG_LIST_FORMAT if tag_list_type == 'cloud': #force cloud to sort by name related_tags = sorted(related_tags, key=operator.attrgetter('name')) contributors = list( models.Thread.objects.get_thread_contributors( thread_list=page.object_list).only('id', 'username', 'gravatar')) paginator_context = { 'is_paginated': (paginator.count > page_size), 'pages': paginator.num_pages, 'page': search_state.page, 'has_previous': page.has_previous(), 'has_next': page.has_next(), 'previous': page.previous_page_number(), 'next': page.next_page_number(), 'base_url': search_state.query_string(), 'page_size': page_size, } # We need to pass the rss feed url based # on the search state to the template. # We use QueryDict to get a querystring # from dicts and arrays. Much cleaner # than parsing and string formating. rss_query_dict = QueryDict("").copy() if search_state.query: # We have search string in session - pass it to # the QueryDict rss_query_dict.update({"q": search_state.query}) if search_state.tags: # We have tags in session - pass it to the # QueryDict but as a list - we want tags+ rss_query_dict.setlist("tags", search_state.tags) context_feed_url = '/feeds/rss/?%s' % rss_query_dict.urlencode( ) # Format the url with the QueryDict reset_method_count = len( filter(None, [ search_state.query, search_state.tags, meta_data.get('author_name', None) ])) if request.is_ajax(): q_count = paginator.count question_counter = ungettext('%(q_num)s question', '%(q_num)s questions', q_count) question_counter = question_counter % { 'q_num': humanize.intcomma(q_count), } if q_count > page_size: paginator_tpl = get_template('main_page/paginator.html', request) paginator_html = paginator_tpl.render( Context({ 'context': functions.setup_paginator(paginator_context), 'questions_count': q_count, 'page_size': page_size, 'search_state': search_state, })) else: paginator_html = '' questions_tpl = get_template('main_page/questions_loop.html', request) questions_html = questions_tpl.render( Context({ 'threads': page, 'search_state': search_state, 'reset_method_count': reset_method_count, })) ajax_data = { 'query_data': { 'tags': search_state.tags, 'sort_order': search_state.sort, 'ask_query_string': search_state.ask_query_string(), }, 'paginator': paginator_html, 'question_counter': question_counter, 'faces': [ extra_tags.gravatar(contributor, 48) for contributor in contributors ], 'feed_url': context_feed_url, 'query_string': search_state.query_string(), 'page_size': page_size, 'questions': questions_html.replace('\n', ''), 'non_existing_tags': meta_data['non_existing_tags'] } ajax_data['related_tags'] = [{ 'name': tag.name, 'used_count': humanize.intcomma(tag.local_used_count) } for tag in related_tags] return HttpResponse(simplejson.dumps(ajax_data), mimetype='application/json') else: # non-AJAX branch template_data = { 'active_tab': 'questions', 'author_name': meta_data.get('author_name', None), 'contributors': contributors, 'context': paginator_context, '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), 'subscribed_tag_names': meta_data.get('subscribed_tag_names', None), 'language_code': translation.get_language(), 'name_of_anonymous_user': models.get_name_of_anonymous_user(), 'page_class': 'main-page', 'page_size': page_size, 'query': search_state.query, 'threads': page, 'questions_count': paginator.count, 'reset_method_count': reset_method_count, 'scope': search_state.scope, 'show_sort_by_relevance': askbot.conf.should_show_sort_by_relevance(), 'search_tags': search_state.tags, 'sort': search_state.sort, 'tab_id': search_state.sort, 'tags': related_tags, 'tag_list_type': tag_list_type, 'font_size': extra_tags.get_tag_font_size(related_tags), 'display_tag_filter_strategy_choices': const.TAG_DISPLAY_FILTER_STRATEGY_CHOICES, 'email_tag_filter_strategy_choices': const.TAG_EMAIL_FILTER_STRATEGY_CHOICES, 'update_avatar_data': schedules.should_update_avatar_data(request), 'query_string': search_state.query_string(), 'search_state': search_state, 'feed_url': context_feed_url, } return render_into_skin('main_page.html', template_data, request)
def application_settings(request): """The context processor function""" # if not request.path.startswith('/' + settings.ASKBOT_URL): # #todo: this is a really ugly hack, will only work # #when askbot is installed not at the home page. # #this will not work for the # #heavy modders of askbot, because their custom pages # #will not receive the askbot settings in the context # #to solve this properly we should probably explicitly # #add settings to the context per page # return {} my_settings = askbot_settings.as_dict() my_settings['LANGUAGE_CODE'] = getattr(request, 'LANGUAGE_CODE', settings.LANGUAGE_CODE) my_settings['LANGUAGE_MODE'] = askbot.get_lang_mode() my_settings['MULTILINGUAL'] = askbot.is_multilingual() my_settings['LANGUAGES_DICT'] = dict(getattr(settings, 'LANGUAGES', [])) my_settings[ 'ALLOWED_UPLOAD_FILE_TYPES'] = settings.ASKBOT_ALLOWED_UPLOAD_FILE_TYPES my_settings['ASKBOT_URL'] = settings.ASKBOT_URL my_settings['STATIC_URL'] = settings.STATIC_URL my_settings['IP_MODERATION_ENABLED'] = getattr( settings, 'ASKBOT_IP_MODERATION_ENABLED', False) my_settings['USE_LOCAL_FONTS'] = getattr(settings, 'ASKBOT_USE_LOCAL_FONTS', False) my_settings['CSRF_COOKIE_NAME'] = settings.CSRF_COOKIE_NAME my_settings['DEBUG'] = settings.DEBUG my_settings['USING_RUNSERVER'] = 'runserver' in sys.argv my_settings['ASKBOT_VERSION'] = askbot.get_version() my_settings['LOGIN_URL'] = url_utils.get_login_url() my_settings['LOGOUT_URL'] = url_utils.get_logout_url() if my_settings['EDITOR_TYPE'] == 'tinymce': tinymce_plugins = settings.TINYMCE_DEFAULT_CONFIG.get('plugins', '').split(',') my_settings['TINYMCE_PLUGINS'] = [v.strip() for v in tinymce_plugins] my_settings[ 'TINYMCE_EDITOR_DESELECTOR'] = settings.TINYMCE_DEFAULT_CONFIG[ 'editor_deselector'] my_settings['TINYMCE_CONFIG_JSON'] = json.dumps( settings.TINYMCE_DEFAULT_CONFIG) else: my_settings['TINYMCE_PLUGINS'] = [] my_settings['TINYMCE_EDITOR_DESELECTOR'] = '' my_settings['LOGOUT_REDIRECT_URL'] = url_utils.get_logout_redirect_url() current_language = get_language() # for some languages we will start searching for shorter words if current_language == 'ja': # we need to open the search box and show info message about # the japanese lang search min_search_word_length = 1 else: min_search_word_length = my_settings['MIN_SEARCH_WORD_LENGTH'] need_scope_links = askbot_settings.ALL_SCOPE_ENABLED or \ askbot_settings.UNANSWERED_SCOPE_ENABLED or \ (request.user.is_authenticated and askbot_settings.FOLLOWED_SCOPE_ENABLED) context = { 'base_url': site_url(''), 'csrf_token': csrf.get_token(request), 'empty_search_state': SearchState.get_empty(), 'min_search_word_length': min_search_word_length, 'current_language_code': current_language, 'settings': my_settings, 'moderation_items': api.get_info_on_moderation_items(request.user), 'need_scope_links': need_scope_links, 'noscript_url': const.DEPENDENCY_URLS['noscript'], } use_askbot_login = '******' in settings.INSTALLED_APPS my_settings['USE_ASKBOT_LOGIN_SYSTEM'] = use_askbot_login if use_askbot_login and request.user.is_anonymous: from askbot.deps.django_authopenid import context as login_context context.update(login_context.login_context(request)) context['group_list'] = json.dumps(make_group_list()) if askbot_settings.EDITOR_TYPE == 'tinymce': from tinymce.widgets import TinyMCE context['tinymce'] = TinyMCE() return context
def questions(request, **kwargs): """ List of Questions, Tagged questions, and Unanswered questions. matching search query or user selection """ #before = timezone.now() if request.method != 'GET': return HttpResponseNotAllowed(['GET']) #①request.user.is_authenticated()=False search_state = SearchState( user_logged_in=request.user.is_authenticated(), **kwargs ) #①request.user=AnonymousUser: AnonymousUser, #①search_state=scope:all/sort:activity-desc/page:1/ qs, meta_data = models.Thread.objects.run_advanced_search( request_user=request.user, search_state=search_state ) #meta_data={'non_existing_tags': []} if meta_data['non_existing_tags']: search_state = search_state.remove_tags(meta_data['non_existing_tags']) #①qs=[],search_state.page_size=30 paginator = Paginator(qs, search_state.page_size) if paginator.num_pages < search_state.page: search_state.page = 1 page = paginator.page(search_state.page) page.object_list = list(page.object_list) # evaluate the queryset # INFO: Because for the time being we need question posts and thread authors # down the pipeline, we have to precache them in thread objects #①page.object_list=[] models.Thread.objects.precache_view_data_hack(threads=page.object_list) related_tags = Tag.objects.get_related_to_search( threads=page.object_list, ignored_tag_names=meta_data.get('ignored_tag_names',[]) ) tag_list_type = askbot_settings.TAG_LIST_FORMAT #①tag_list_type=u'list' if tag_list_type == 'cloud': #force cloud to sort by name related_tags = sorted(related_tags, key = operator.attrgetter('name')) contributors = list( models.Thread.objects.get_thread_contributors( thread_list=page.object_list ).only( 'id', 'username', 'askbot_profile__gravatar' ) ) paginator_context = { 'is_paginated' : (paginator.count > search_state.page_size), 'pages': paginator.num_pages, 'current_page_number': search_state.page, 'page_object': page, 'base_url' : search_state.query_string(), 'page_size' : search_state.page_size, } #get url for the rss feed context_feed_url = reverse('latest_questions_feed') #①context_feed_url=u'/feeds/rss/' # We need to pass the rss feed url based # on the search state to the template. # We use QueryDict to get a querystring # from dicts and arrays. Much cleaner # than parsing and string formating. rss_query_dict = QueryDict("").copy() #①search_state.query=None if search_state.query: # We have search string in session - pass it to # the QueryDict rss_query_dict.update({"q": search_state.query}) #①search_state.tags=None if search_state.tags: # We have tags in session - pass it to the # QueryDict but as a list - we want tags+ rss_query_dict.setlist('tags', search_state.tags) context_feed_url += '?' + rss_query_dict.urlencode() reset_method_count = len(filter(None, [search_state.query, search_state.tags, meta_data.get('author_name', None)])) if request.is_ajax(): q_count = paginator.count #todo: words question_counter = ungettext('%(q_num)s question', '%(q_num)s questions', q_count) question_counter = question_counter % {'q_num': humanize.intcomma(q_count),} if q_count > search_state.page_size: paginator_tpl = get_template('main_page/paginator.html') paginator_html = paginator_tpl.render( RequestContext( request, { 'context': paginator_context, 'questions_count': q_count, 'page_size' : search_state.page_size, 'search_state': search_state, } ) ) else: paginator_html = '' questions_tpl = get_template('main_page/questions_loop.html') questions_html = questions_tpl.render( RequestContext( request, { 'threads': page, 'search_state': search_state, 'reset_method_count': reset_method_count, 'request': request } ) ) ajax_data = { 'query_data': { 'tags': search_state.tags, 'sort_order': search_state.sort, 'ask_query_string': search_state.ask_query_string(), }, 'paginator': paginator_html, 'question_counter': question_counter, 'faces': [],#[extra_tags.gravatar(contributor, 48) for contributor in contributors], 'feed_url': context_feed_url, 'query_string': search_state.query_string(), 'page_size' : search_state.page_size, 'questions': questions_html.replace('\n',''), 'non_existing_tags': meta_data['non_existing_tags'], } related_tags_tpl = get_template('widgets/related_tags.html') related_tags_data = { 'tags': related_tags, 'tag_list_type': tag_list_type, 'query_string': search_state.query_string(), 'search_state': search_state, 'language_code': translation.get_language(), } if tag_list_type == 'cloud': related_tags_data['font_size'] = extra_tags.get_tag_font_size(related_tags) ajax_data['related_tags_html'] = related_tags_tpl.render( RequestContext(request, related_tags_data) ) #here we add and then delete some items #to allow extra context processor to work ajax_data['tags'] = related_tags ajax_data['interesting_tag_names'] = None ajax_data['threads'] = page extra_context = context.get_extra( 'ASKBOT_QUESTIONS_PAGE_EXTRA_CONTEXT', request, ajax_data ) del ajax_data['tags'] del ajax_data['interesting_tag_names'] del ajax_data['threads'] ajax_data.update(extra_context) return HttpResponse(simplejson.dumps(ajax_data), content_type='application/json') else: # non-AJAX branch template_data = { 'active_tab': 'questions', 'author_name' : meta_data.get('author_name',None), 'contributors' : contributors, 'context' : paginator_context, '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), 'subscribed_tag_names': meta_data.get('subscribed_tag_names', None), 'language_code': translation.get_language(), 'name_of_anonymous_user' : models.get_name_of_anonymous_user(), 'page_class': 'main-page', 'page_size': search_state.page_size, 'query': search_state.query, 'threads' : page, 'questions_count' : paginator.count, 'reset_method_count': reset_method_count, 'scope': search_state.scope, 'show_sort_by_relevance': conf.should_show_sort_by_relevance(), 'search_tags' : search_state.tags, 'sort': search_state.sort, 'tab_id' : search_state.sort, 'tags' : related_tags, 'tag_list_type' : tag_list_type, 'font_size' : extra_tags.get_tag_font_size(related_tags), 'display_tag_filter_strategy_choices': conf.get_tag_display_filter_strategy_choices(), 'email_tag_filter_strategy_choices': conf.get_tag_email_filter_strategy_choices(), 'query_string': search_state.query_string(), 'search_state': search_state, 'feed_url': context_feed_url } extra_context = context.get_extra( 'ASKBOT_QUESTIONS_PAGE_EXTRA_CONTEXT', request, template_data ) template_data.update(extra_context) template_data.update(context.get_for_tag_editor()) #and one more thing:) give admin user heads up about #setting the domain name if they have not done that yet #todo: move this out to a separate middleware if request.user.is_authenticated() and request.user.is_administrator(): if domain_is_bad(): url = askbot_settings.get_setting_url(('QA_SITE_SETTINGS', 'APP_URL')) msg = _( 'Please go to Settings -> %s ' 'and set the base url for your site to function properly' ) % url request.user.message_set.create(message=msg) #①template_data={'contributors': [], 'ignored_tag_names': None, 'author_name': None, 'language_code': 'en', 'active_tab': 'questions', 'query': None, 'tag_list_type': u'list', 'display_tag_filter_strategy_choices': ((0, <django.utils.functional.__proxy__ object at 0x00000000059CDF28>), (1, <django.utils.functional.__proxy__ object at 0x00000000059CDF98>), (2, <django.utils.functional.__proxy__ object at 0x00000000059D5048>)), 'is_unanswered': False, 'feed_url': u'/feeds/rss/', 'questions_count': 0, 'tags': [], 'page_size': 30, 'search_state': <askbot.search.state_manager.SearchState object at 0x0000000006D9ECC0>, 'tab_id': 'activity-desc', 'sort': 'activity-desc', 'context': {'page_object': <Page 1 of 1>, 'base_url': u'scope:all/sort:activity-desc/page:1/', 'page_size': 30, 'current_page_number': 1, 'is_paginated': False, 'pages': 1}, 'search_tags': [], 'reset_method_count': 0, 'subscribed_tag_names': None, 'threads': <Page 1 of 1>, 'scope': u'all', 'font_size': {}, 'email_tag_filter_strategy_choices': ((0, <django.utils.functional.__proxy__ object at 0x00000000059D5128>), (1, <django.utils.functional.__proxy__ object at 0x00000000059D5198>), (2, <django.utils.functional.__proxy__ object at 0x00000000059D5208>)), 'show_sort_by_relevance': False, 'tag_editor_settings': '{"tag_forbidden_first_chars": "#", "max_tag_length": 20, "force_lowercase_tags": false, "max_tags_per_post": 5, "messages": {"wrong_first_char": "# is not a valid character at the beginning of tags, use only letters and numbers", "wrong_chars": "please use letters, numbers and characters \\"-+.#\\"", "required": "tags are required"}, "tags_are_required": false}', 'page_class': 'main-page', 'query_string': u'scope:all/sort:activity-desc/page:1/', 'name_of_anonymous_user': u'Anonymous', 'interesting_tag_names': None} return render(request, 'main_page.html', template_data)
def questions(request, **kwargs): """ List of Questions, Tagged questions, and Unanswered questions. matching search query or user selection """ # before = datetime.datetime.now() if request.method != "GET": return HttpResponseNotAllowed(["GET"]) search_state = SearchState(user_logged_in=request.user.is_authenticated(), **kwargs) page_size = int(askbot_settings.DEFAULT_QUESTIONS_PAGE_SIZE) qs, meta_data = models.Thread.objects.run_advanced_search(request_user=request.user, search_state=search_state) if meta_data["non_existing_tags"]: search_state = search_state.remove_tags(meta_data["non_existing_tags"]) paginator = Paginator(qs, page_size) if paginator.num_pages < search_state.page: search_state.page = 1 page = paginator.page(search_state.page) page.object_list = list(page.object_list) # evaluate the queryset # INFO: Because for the time being we need question posts and thread authors # down the pipeline, we have to precache them in thread objects models.Thread.objects.precache_view_data_hack(threads=page.object_list) related_tags = Tag.objects.get_related_to_search( threads=page.object_list, ignored_tag_names=meta_data.get("ignored_tag_names", []) ) tag_list_type = askbot_settings.TAG_LIST_FORMAT if tag_list_type == "cloud": # force cloud to sort by name related_tags = sorted(related_tags, key=operator.attrgetter("name")) contributors = list( models.Thread.objects.get_thread_contributors(thread_list=page.object_list).only("id", "username", "gravatar") ) paginator_context = { "is_paginated": (paginator.count > page_size), "pages": paginator.num_pages, "page": search_state.page, "has_previous": page.has_previous(), "has_next": page.has_next(), "previous": page.previous_page_number(), "next": page.next_page_number(), "base_url": search_state.query_string(), "page_size": page_size, } # We need to pass the rss feed url based # on the search state to the template. # We use QueryDict to get a querystring # from dicts and arrays. Much cleaner # than parsing and string formating. rss_query_dict = QueryDict("").copy() if search_state.query: # We have search string in session - pass it to # the QueryDict rss_query_dict.update({"q": search_state.query}) if search_state.tags: # We have tags in session - pass it to the # QueryDict but as a list - we want tags+ rss_query_dict.setlist("tags", search_state.tags) context_feed_url = "/%sfeeds/rss/?%s" % ( settings.ASKBOT_URL, rss_query_dict.urlencode(), ) # Format the url with the QueryDict reset_method_count = len(filter(None, [search_state.query, search_state.tags, meta_data.get("author_name", None)])) if request.is_ajax(): q_count = paginator.count question_counter = ungettext("%(q_num)s question", "%(q_num)s questions", q_count) question_counter = question_counter % {"q_num": humanize.intcomma(q_count)} if q_count > page_size: paginator_tpl = get_template("main_page/paginator.html", request) paginator_html = paginator_tpl.render( Context( { "context": functions.setup_paginator(paginator_context), "questions_count": q_count, "page_size": page_size, "search_state": search_state, } ) ) else: paginator_html = "" questions_tpl = get_template("main_page/questions_loop.html", request) questions_html = questions_tpl.render( Context( { "threads": page, "search_state": search_state, "reset_method_count": reset_method_count, "request": request, } ) ) ajax_data = { "query_data": { "tags": search_state.tags, "sort_order": search_state.sort, "ask_query_string": search_state.ask_query_string(), }, "paginator": paginator_html, "question_counter": question_counter, "faces": [], # [extra_tags.gravatar(contributor, 48) for contributor in contributors], "feed_url": context_feed_url, "query_string": search_state.query_string(), "page_size": page_size, "questions": questions_html.replace("\n", ""), "non_existing_tags": meta_data["non_existing_tags"], } ajax_data["related_tags"] = [ {"name": escape(tag.name), "used_count": humanize.intcomma(tag.local_used_count)} for tag in related_tags ] return HttpResponse(simplejson.dumps(ajax_data), mimetype="application/json") else: # non-AJAX branch template_data = { "active_tab": "questions", "author_name": meta_data.get("author_name", None), "contributors": contributors, "context": paginator_context, "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), "subscribed_tag_names": meta_data.get("subscribed_tag_names", None), "language_code": translation.get_language(), "name_of_anonymous_user": models.get_name_of_anonymous_user(), "page_class": "main-page", "page_size": page_size, "query": search_state.query, "threads": page, "questions_count": paginator.count, "reset_method_count": reset_method_count, "scope": search_state.scope, "show_sort_by_relevance": conf.should_show_sort_by_relevance(), "search_tags": search_state.tags, "sort": search_state.sort, "tab_id": search_state.sort, "tags": related_tags, "tag_list_type": tag_list_type, "font_size": extra_tags.get_tag_font_size(related_tags), "display_tag_filter_strategy_choices": conf.get_tag_display_filter_strategy_choices(), "email_tag_filter_strategy_choices": const.TAG_EMAIL_FILTER_STRATEGY_CHOICES, "update_avatar_data": schedules.should_update_avatar_data(request), "query_string": search_state.query_string(), "search_state": search_state, "feed_url": context_feed_url, } return render_into_skin("main_page.html", template_data, request)