Example #1
0
    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()

        )
Example #6
0
    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()),
        )
Example #7
0
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)
Example #8
0
 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())
Example #9
0
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)
Example #10
0
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')
Example #11
0
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')
Example #12
0
 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
Example #13
0
    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)
Example #14
0
    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)
Example #15
0
    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())
Example #16
0
    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())
Example #17
0
 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())
Example #18
0
 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()
     )
Example #19
0
    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()
        )
Example #21
0
    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
Example #22
0
    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)
Example #23
0
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
Example #25
0
    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
Example #26
0
 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)
Example #27
0
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)
Example #28
0
    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)
Example #29
0
    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)
Example #30
0
    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
Example #31
0
    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)
Example #32
0
    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)
Example #33
0
    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 `&lt;` was `&amp;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(
            '&lt;&lt;&lt;tag1&gt;&gt;&gt; fake title' in proper_html)
        #self.assertTrue('&lt;&lt;&lt;tag2&gt;&gt;&gt; &lt;&lt;&lt;tag3&gt;&gt;&gt; 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)
Example #34
0
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())
Example #36
0
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)
Example #38
0
    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)
Example #39
0
 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 `&lt;` was `&amp;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('&lt;&lt;&lt;tag1&gt;&gt;&gt; fake title' in proper_html)
        #self.assertTrue('&lt;&lt;&lt;tag2&gt;&gt;&gt; &lt;&lt;&lt;tag3&gt;&gt;&gt; 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)
Example #41
0
    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
Example #42
0
def get_empty_search_state(unused):
    from askbot.search.state_manager import SearchState
    return SearchState.get_empty()
Example #43
0
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)
Example #44
0
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)
Example #45
0
 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())
Example #46
0
    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,
        )
Example #47
0
    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,
            )
Example #48
0
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)
Example #49
0
 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())
Example #50
0
 def test_cannot_add_already_added_tag(self):
     ss = SearchState.get_empty().add_tag('double').add_tag('double')
     self.assertListEqual(['double'], ss.tags)
Example #51
0
    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)
Example #52
0
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 get_empty_search_state(unused):
    from askbot.search.state_manager import SearchState

    return SearchState.get_empty()
Example #54
0
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)
Example #55
0
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)
Example #56
0
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
Example #57
0
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)
Example #58
0
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)