Example #1
0
 def query_string(self):
     lst = [
         'scope:%s' % self.scope,
         'sort:%s-%s' % (self.sort_method, self.sort_dir)
     ]
     if self.query:
         lst.append(
             'query:' +
             urllib.quote(smart_str(self.query), safe=self.SAFE_CHARS))
     if self.tags:
         lst.append('tags:' +
                    urllib.quote(smart_str(const.TAG_SEP.join(self.tags)),
                                 safe=self.SAFE_CHARS))
     if self.author:
         if isinstance(self.author, (list, tuple, set)):
             ids = self.author
         else:
             ids = extract_numbers(self.author)
         ids = User.objects.filter(pk__in=ids,
                                   is_active=True,
                                   is_hidden=False).values_list("pk",
                                                                flat=True)
         lst.append('author:' + "[%s]" % ",".join([str(ch) for ch in ids]))
     if self.page:
         lst.append('page:' + str(self.page))
     return '/'.join(lst) + '/'
Example #2
0
def node_module_thread(request, node, module, **kwargs):

    redirect = False
    search_user_form = SearchUserForm(request.GET)
    if search_user_form.is_valid():
        ids = [
            int(_id) for _id in
            extract_numbers(search_user_form.data["authors"])
        ]
        kwargs.update({"author": ids})
        redirect = True

    search_state = SearchState(
        user_logged_in=request.user.is_authenticated(),
        node=node,
        module=module,
        request=request,
        **kwargs
        )

    if redirect:
        return HttpResponseRedirect(search_state.full_url())

    if search_state.author:
        search_user_form.data["authors"] = extract_numbers(search_state.author)

    page_size = int(openode_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 = openode_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)

    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('node/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('node/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],
        #     '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]

        ajax_data = {"msg": "bad request"}
        node.visit(request.user)
        return HttpResponse(simplejson.dumps(ajax_data), mimetype='application/json')

    else:  # non-AJAX branch

        template_data = {
            # ThreadCategory Tree root
            "categories": node.thread_categories.filter(level=0),
            "search_user_form": search_user_form,
            'active_tab': 'questions',
            'authors': meta_data.get('authors', []),
            '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,
            'threads': page,
            'questions_count': paginator.count,
            'reset_method_count': reset_method_count,
            '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),
            'search_state': search_state,
            'node': node,
            'module': module
        }

        # load opened nodes from session
        opened_categories = list(
            request.session.setdefault(
                OPENED_CATEGORIES_KEY,
                set()
                # set(ThreadCategory.objects.filter(display_opened=True).values_list("pk", flat=True))
            )
        )
        template_data.update({"opened_categories": opened_categories})

        template_file = NODE_MODULE_TEMPLATE_FILE[module]

        if module == 'library':

            # get categories (with path to root) with thread (documents) with is unread
            # maybe is better way to create document/category tree structure in python and in template only render.

            categories_ids_witn_unread_thread = set()

            def _recursively(categories):
                for category in categories.iterator():
                    for thread in category.threads.iterator():
                        if thread.has_unread_main_post_for_user(request.user):
                            categories_ids_witn_unread_thread.update(
                                category.get_ancestors(include_self=True).values_list("pk", flat=True)
                            )
                            break
                    _recursively(category.get_children())
            _recursively(node.thread_categories.filter(level=0))

            ####################################################################

            template_data.update({
                "download_zip_form": DownloadZipForm(),
                "free_threads": node.threads.filter(is_deleted=False, category=None, thread_type=const.THREAD_TYPE_DOCUMENT).order_by("title"),  # Thread.objects.filter(thread__node=node, thread__category=None).select_related("thread"),
                "categories_ids_witn_unread_thread": categories_ids_witn_unread_thread
                # "categorized_threads": node.threads.exclude(category=None),  # Thread.objects.filter(thread__node=node, thread__category=None).select_related("thread"),
                # "free_documents": Document.objects.filter(thread__node=node, thread__category=None).select_related("thread"),
                # "category_documents": Document.objects.filter(thread__node=node).exclude(thread__category=None),
            })
        node.visit(request.user)
        return render_into_skin(template_file, template_data, request)
Example #3
0
def node_module_thread(request, node, module, **kwargs):
    redirect = False
    search_user_form = SearchUserForm(request.GET)
    if search_user_form.is_valid():
        ids = [
            int(_id) for _id in
            extract_numbers(search_user_form.data["authors"])
        ]
        kwargs.update({"author": ids})
        redirect = True

    search_state = SearchState(
        user_logged_in=request.user.is_authenticated(),
        node=node,
        module=module,
        request=request,
        **kwargs
        )

    if redirect:
        return HttpResponseRedirect(search_state.full_url())

    if search_state.author:
        search_user_form.data["authors"] = extract_numbers(search_state.author)

    page_size = int(openode_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 = openode_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)

    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('node/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('node/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],
        #     '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]

        ajax_data = {"msg": "bad request"}
        node.visit(request.user)
        return HttpResponse(simplejson.dumps(ajax_data), mimetype='application/json')

    else:  # non-AJAX branch

        template_data = {
            # ThreadCategory Tree root
            "categories": node.thread_categories.filter(level=0),
            "search_user_form": search_user_form,
            'active_tab': 'questions',
            'authors': meta_data.get('authors', []),
            '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,
            'threads': page,
            'questions_count': paginator.count,
            'reset_method_count': reset_method_count,
            '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),
            'search_state': search_state,
            'node': node,
            'module': module
        }

        # load opened nodes from session
        opened_categories = list(
            request.session.setdefault(
                OPENED_CATEGORIES_KEY,
                set()
                # set(ThreadCategory.objects.filter(display_opened=True).values_list("pk", flat=True))
            )
        )
        template_data.update({"opened_categories": opened_categories})

        template_file = NODE_MODULE_TEMPLATE_FILE[module]

        if module == 'library':

            # get categories (with path to root) with thread (documents) with is unread
            # maybe is better way to create document/category tree structure in python and in template only render.

            categories_ids_witn_unread_thread = set()

            def _recursively(categories):
                for category in categories.iterator():
                    for thread in category.threads.iterator():
                        if thread.has_unread_main_post_for_user(request.user):
                            categories_ids_witn_unread_thread.update(
                                category.get_ancestors(include_self=True).values_list("pk", flat=True)
                            )
                            break
                    _recursively(category.get_children())
            _recursively(node.thread_categories.filter(level=0))

            ####################################################################

            template_data.update({
                "download_zip_form": DownloadZipForm(),
                "free_threads": node.threads.filter(is_deleted=False, category=None, thread_type=const.THREAD_TYPE_DOCUMENT).order_by("title"),  # Thread.objects.filter(thread__node=node, thread__category=None).select_related("thread"),
                "categories_ids_witn_unread_thread": categories_ids_witn_unread_thread
                # "categorized_threads": node.threads.exclude(category=None),  # Thread.objects.filter(thread__node=node, thread__category=None).select_related("thread"),
                # "free_documents": Document.objects.filter(thread__node=node, thread__category=None).select_related("thread"),
                # "category_documents": Document.objects.filter(thread__node=node).exclude(thread__category=None),
            })
        node.visit(request.user)
        return render_into_skin(template_file, template_data, request)
Example #4
0
            return HttpResponseRedirect(show_post.get_absolute_url())

        try:
            show_post.assert_is_visible_to(request.user)
        except django_exceptions.PermissionDenied, error:
            request.user.message_set.create(message=unicode(error))
            return HttpResponseRedirect(thread.get_absolute_url())

    # logging.debug('answer_sort_method=' + unicode(answer_sort_method))

    #load answers and post id's->athor_id mapping
    #posts are pre-stuffed with the correctly ordered comments

    # authors = request.GET.get("authors", "")
    from openode.utils.text import extract_numbers
    authors_ids = extract_numbers(request.GET.get("authors", ""))
    authors = []

    qs = None
    if authors_ids:
        authors = User.objects.filter(
            pk__in=authors_ids,
            is_active=True,
            is_hidden=False
        )
        qs = thread.posts.filter(
            author__in=authors,
            deleted=False
        )

    updated_main_post, answers, post_to_author = thread.get_cached_post_data(
Example #5
0
            return HttpResponseRedirect(show_post.get_absolute_url())

        try:
            show_post.assert_is_visible_to(request.user)
        except django_exceptions.PermissionDenied, error:
            request.user.message_set.create(message=unicode(error))
            return HttpResponseRedirect(thread.get_absolute_url())

    # logging.debug('answer_sort_method=' + unicode(answer_sort_method))

    # load answers and post id's->athor_id mapping
    # posts are pre-stuffed with the correctly ordered comments

    # authors = request.GET.get("authors", "")
    from openode.utils.text import extract_numbers
    authors_ids = extract_numbers(request.GET.get("authors", ""))
    authors = []

    qs = None
    if authors_ids:
        authors = User.objects.filter(pk__in=authors_ids,
                                      is_active=True,
                                      is_hidden=False)
        qs = thread.posts.filter(author__in=authors, deleted=False)

    # Question flow: show only published answers
    if node.is_question_flow_enabled and (
            request.user not in thread.node.get_responsible_persons()):
        qs = qs or thread.posts.all()
        qs = qs.filter(
            pk=thread.accepted_answer_id