Пример #1
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' % (
                            django_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': conf.get_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,
        }

        extra_context = context.get_extra(
                                    'ASKBOT_QUESTIONS_PAGE_EXTRA_CONTEXT',
                                    request,
                                    template_data
                                )
        template_data.update(extra_context)

        return render(request, 'main_page.html', template_data)
Пример #2
0
def edit_answer(request, id):
    answer = get_object_or_404(models.Post, id=id)

    if askbot_settings.READ_ONLY_MODE_ENABLED:
        return HttpResponseRedirect(answer.get_absolute_url())

    try:
        revision = answer.revisions.get(revision=0)
    except models.PostRevision.DoesNotExist:
        revision = answer.get_latest_revision()

    class_path = getattr(settings, 'ASKBOT_EDIT_ANSWER_FORM', None)
    if class_path:
        edit_answer_form_class = load_module(class_path)
    else:
        edit_answer_form_class = forms.EditAnswerForm

    try:
        request.user.assert_can_edit_answer(answer)
        if request.method == "POST":
            if request.POST['select_revision'] == 'true':
                # user has changed revistion number
                revision_form = forms.RevisionForm(
                                                answer,
                                                revision,
                                                request.POST
                                            )
                if revision_form.is_valid():
                    # Replace with those from the selected revision
                    rev = revision_form.cleaned_data['revision']
                    revision = answer.revisions.get(revision = rev)
                    form = edit_answer_form_class(
                                    answer, revision, user=request.user
                                )
                else:
                    form = edit_answer_form_class(
                                                answer,
                                                revision,
                                                request.POST,
                                                user=request.user
                                            )
            else:
                form = edit_answer_form_class(
                    answer, revision, request.POST, user=request.user
                )
                revision_form = forms.RevisionForm(answer, revision)

                if form.is_valid():
                    if form.has_changed():
                        user = form.get_post_user(request.user)
                        suppress_email = form.cleaned_data['suppress_email']
                        is_private = form.cleaned_data.get('post_privately', False)
                        user.edit_answer(
                            answer=answer,
                            body_text=form.cleaned_data['text'],
                            revision_comment=form.cleaned_data['summary'],
                            wiki=form.cleaned_data.get('wiki', answer.wiki),
                            is_private=is_private,
                            suppress_email=suppress_email,
                            ip_addr=request.META.get('REMOTE_ADDR')
                        )

                        signals.answer_edited.send(None,
                            answer=answer,
                            user=user,
                            form_data=form.cleaned_data
                        )

                    return HttpResponseRedirect(answer.get_absolute_url())
        else:
            revision_form = forms.RevisionForm(answer, revision)
            form = edit_answer_form_class(answer, revision, user=request.user)
            if request.user.can_make_group_private_posts():
                form.initial['post_privately'] = answer.is_private()

        data = {
            'page_class': 'edit-answer-page',
            'active_tab': 'questions',
            'answer': answer,
            'revision': revision,
            'revision_form': revision_form,
            'form': form,
        }
        extra_context = context.get_extra(
            'ASKBOT_EDIT_ANSWER_PAGE_EXTRA_CONTEXT',
            request,
            data
        )
        data.update(extra_context)

        return render(request, 'answer_edit.html', data)

    except exceptions.PermissionDenied, e:
        request.user.message_set.create(message = unicode(e))
        return HttpResponseRedirect(answer.get_absolute_url())
Пример #3
0
        'tab_id' : answer_sort_method,
        'favorited' : favorited,
        'similar_threads' : thread.get_similar_threads(),
        'language_code': translation.get_language(),
        'paginator_context' : paginator_context,
        'show_post': show_post,
        'show_comment': show_comment,
        'show_comment_position': show_comment_position,
    }
    #shared with ...
    if askbot_settings.GROUPS_ENABLED:
        data['sharing_info'] = thread.get_sharing_info()

    data.update(context.get_for_tag_editor())

    extra = context.get_extra('ASKBOT_QUESTION_PAGE_EXTRA_CONTEXT', request, data)
    data.update(extra)

    return render(request, 'question.html', data)

def revisions(request, id, post_type = None):
    assert post_type in ('question', 'answer')
    post = get_object_or_404(models.Post, post_type=post_type, id=id)
    revisions = list(models.PostRevision.objects.filter(post=post))
    revisions.reverse()
    for i, revision in enumerate(revisions):
        if i == 0:
            revision.diff = sanitize_html(revisions[i].html)
            revision.summary = _('initial version')
        else:
            revision.diff = htmldiff(
Пример #4
0
def tags(request):#view showing a listing of available tags - plain list

    #1) Get parameters. This normally belongs to form cleaning.
    post_data = request.GET
    sortby = post_data.get('sort', 'used')
    try:
        page = int(post_data.get('page', '1'))
    except ValueError:
        page = 1

    if sortby == 'name':
        order_by = 'name'
    else:
        order_by = '-used_count'

    query = post_data.get('query', '').strip()
    tag_list_type = askbot_settings.TAG_LIST_FORMAT

    #2) Get query set for the tags.
    query_params = {'deleted': False}
    if query != '':
        query_params['name__icontains'] = query

    tags_qs = Tag.objects.filter(**query_params).exclude(used_count=0)

    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,
        'stag' : query,
        'tab_id' : sortby,
        'keywords' : query,
        'search_state': SearchState(*[None for x in range(7)])
    }

    if tag_list_type == 'list':
        #plain listing is paginated
        objects_list = Paginator(tags_qs, DEFAULT_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,
            'page': page,
            'has_previous': tags.has_previous(),
            'has_next': tags.has_next(),
            'previous': tags.previous_page_number(),
            'next': tags.next_page_number(),
            'base_url' : reverse('tags') + '?sort=%s&amp;' % sortby
        }
        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, mimetype='application/json')
    else:
        return render(request, 'tags.html', data)
Пример #5
0
def tags(request):  #view showing a listing of available tags - plain list

    #1) Get parameters. This normally belongs to form cleaning.
    post_data = request.GET
    sortby = post_data.get('sort', 'used')
    try:
        page = int(post_data.get('page', '1'))
    except ValueError:
        page = 1

    if sortby == 'name':
        order_by = 'name'
    else:
        order_by = '-used_count'

    query = post_data.get('query', '').strip()
    tag_list_type = askbot_settings.TAG_LIST_FORMAT

    #2) Get query set for the tags.
    query_params = {'deleted': False}
    if query != '':
        query_params['name__icontains'] = query

    tags_qs = Tag.objects.filter(**query_params).exclude(used_count=0)

    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,
        'stag': query,
        'tab_id': sortby,
        'keywords': query,
        'search_state': SearchState(*[None for x in range(7)])
    }

    if tag_list_type == 'list':
        #plain listing is paginated
        objects_list = Paginator(tags_qs, DEFAULT_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&amp;' % sortby
        }
        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, mimetype='application/json')
    else:
        return render(request, 'tags.html', data)
Пример #6
0
def edit_answer(request, id):
    answer = get_object_or_404(models.Post, id=id)

    if askbot_settings.READ_ONLY_MODE_ENABLED:
        return HttpResponseRedirect(answer.get_absolute_url())

    revision = answer.get_latest_revision()

    class_path = getattr(settings, "ASKBOT_EDIT_ANSWER_FORM", None)
    if class_path:
        edit_answer_form_class = load_module(class_path)
    else:
        edit_answer_form_class = forms.EditAnswerForm

    try:
        request.user.assert_can_edit_answer(answer)
        if request.method == "POST":
            if request.POST["select_revision"] == "true":
                # user has changed revistion number
                revision_form = forms.RevisionForm(answer, revision, request.POST)
                if revision_form.is_valid():
                    # Replace with those from the selected revision
                    rev = revision_form.cleaned_data["revision"]
                    revision = answer.revisions.get(revision=rev)
                    form = edit_answer_form_class(answer, revision, user=request.user)
                else:
                    form = edit_answer_form_class(answer, revision, request.POST, user=request.user)
            else:
                form = edit_answer_form_class(answer, revision, request.POST, user=request.user)
                revision_form = forms.RevisionForm(answer, revision)

                if form.is_valid():
                    if form.has_changed():
                        user = form.get_post_user(request.user)
                        suppress_email = form.cleaned_data["suppress_email"]
                        is_private = form.cleaned_data.get("post_privately", False)
                        user.edit_answer(
                            answer=answer,
                            body_text=form.cleaned_data["text"],
                            revision_comment=form.cleaned_data["summary"],
                            wiki=form.cleaned_data.get("wiki", answer.wiki),
                            is_private=is_private,
                            suppress_email=suppress_email,
                            ip_addr=request.META.get("REMOTE_ADDR"),
                        )

                        signals.answer_edited.send(None, answer=answer, user=user, form_data=form.cleaned_data)

                    return HttpResponseRedirect(answer.get_absolute_url())
        else:
            revision_form = forms.RevisionForm(answer, revision)
            form = edit_answer_form_class(answer, revision, user=request.user)
            if request.user.can_make_group_private_posts():
                form.initial["post_privately"] = answer.is_private()

        data = {
            "page_class": "edit-answer-page",
            "active_tab": "questions",
            "answer": answer,
            "revision": revision,
            "revision_form": revision_form,
            "form": form,
        }
        extra_context = context.get_extra("ASKBOT_EDIT_ANSWER_PAGE_EXTRA_CONTEXT", request, data)
        data.update(extra_context)

        return render(request, "answer_edit.html", data)

    except exceptions.PermissionDenied, e:
        request.user.message_set.create(message=unicode(e))
        return HttpResponseRedirect(answer.get_absolute_url())
Пример #7
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)
Пример #8
0
def question(request, id):#refactor - long subroutine. display question body, answers and comments
    """view that displays body of the question and
    all answers to it

    todo: convert this view into class
    """
    #process url parameters
    #todo: fix inheritance of sort method from questions
    #before = timezone.now()
    form = ShowQuestionForm(request.REQUEST)
    form.full_clean()#always valid
    show_answer = form.cleaned_data['show_answer']
    show_comment = form.cleaned_data['show_comment']
    show_page = form.cleaned_data['show_page']
    answer_sort_method = form.cleaned_data['answer_sort_method']

    #load question and maybe refuse showing deleted question
    #if the question does not exist - try mapping to old questions
    #and and if it is not found again - then give up
    try:
        question_post = models.Post.objects.filter(
                                post_type = 'question',
                                id = id
                            ).select_related('thread')[0]
    except IndexError:
    # Handle URL mapping - from old Q/A/C/ URLs to the new one
        try:
            question_post = models.Post.objects.filter(
                                    post_type='question',
                                    old_question_id = id
                                ).select_related('thread')[0]
        except IndexError:
            raise Http404

        if show_answer:
            try:
                old_answer = models.Post.objects.get_answers().get(old_answer_id=show_answer)
            except models.Post.DoesNotExist:
                pass
            else:
                return HttpResponseRedirect(old_answer.get_absolute_url())

        elif show_comment:
            try:
                old_comment = models.Post.objects.get_comments().get(old_comment_id=show_comment)
            except models.Post.DoesNotExist:
                pass
            else:
                return HttpResponseRedirect(old_comment.get_absolute_url())

    if show_comment or show_answer:
        try:
            show_post = models.Post.objects.get(pk=(show_comment or show_answer))
        except models.Post.DoesNotExist:
            #missing target post will be handled later
            pass
        else:
            if (show_comment and not show_post.is_comment()) \
                or (show_answer and not show_post.is_answer()):
                return HttpResponseRedirect(show_post.get_absolute_url())

    try:
        question_post.assert_is_visible_to(request.user)
    except exceptions.QuestionHidden as error:
        request.user.message_set.create(message = unicode(error))
        return HttpResponseRedirect(reverse('index'))

    #redirect if slug in the url is wrong
    if request.path.split('/')[-2] != question_post.slug:
        logging.debug('no slug match!')
        lang = translation.get_language()
        question_url = question_post.get_absolute_url(language=lang)
        if request.GET:
            question_url += u'?' + urllib.urlencode(request.GET)
        return HttpResponseRedirect(question_url)


    #resolve comment and answer permalinks
    #they go first because in theory both can be moved to another question
    #this block "returns" show_post and assigns actual comment and answer
    #to show_comment and show_answer variables
    #in the case if the permalinked items or their parents are gone - redirect
    #redirect also happens if id of the object's origin post != requested id
    show_post = None #used for permalinks
    if show_comment:
        #if url calls for display of a specific comment,
        #check that comment exists, that it belongs to
        #the current question
        #if it is an answer comment and the answer is hidden -
        #redirect to the default view of the question
        #if the question is hidden - redirect to the main page
        #in addition - if url points to a comment and the comment
        #is for the answer - we need the answer object
        try:
            show_comment = models.Post.objects.get_comments().get(id=show_comment)
        except models.Post.DoesNotExist:
            error_message = _(
                'Sorry, the comment you are looking for has been '
                'deleted and is no longer accessible'
            )
            request.user.message_set.create(message = error_message)
            return HttpResponseRedirect(question_post.thread.get_absolute_url())

        if str(show_comment.thread._question_post().id) != str(id):
            return HttpResponseRedirect(show_comment.get_absolute_url())
        show_post = show_comment.parent

        try:
            show_comment.assert_is_visible_to(request.user)
        except exceptions.AnswerHidden as error:
            request.user.message_set.create(message = unicode(error))
            #use reverse function here because question is not yet loaded
            return HttpResponseRedirect(reverse('question', kwargs = {'id': id}))
        except exceptions.QuestionHidden as error:
            request.user.message_set.create(message = unicode(error))
            return HttpResponseRedirect(reverse('index'))

    elif show_answer:
        #if the url calls to view a particular answer to
        #question - we must check whether the question exists
        #whether answer is actually corresponding to the current question
        #and that the visitor is allowed to see it
        show_post = get_object_or_404(models.Post, post_type='answer', id=show_answer)
        if str(show_post.thread._question_post().id) != str(id):
            return HttpResponseRedirect(show_post.get_absolute_url())

        try:
            show_post.assert_is_visible_to(request.user)
        except django_exceptions.PermissionDenied as error:
            request.user.message_set.create(message = unicode(error))
            return HttpResponseRedirect(reverse('question', kwargs = {'id': id}))

    thread = question_post.thread

    if askbot.get_lang_mode() == 'url-lang':
        request_lang = translation.get_language()
        if request_lang != thread.language_code:
            template = get_template('question/lang_switch_message.html')
            message = template.render(Context({
                'post_lang': get_language_name(thread.language_code),
                'request_lang': get_language_name(request_lang),
                'home_url': reverse_i18n(request_lang, 'questions')
            }))
            request.user.message_set.create(message=message)
            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
    question_post, answers, post_to_author, published_answer_ids = thread.get_post_data_for_question_view(
                                sort_method=answer_sort_method,
                                user=request.user
                            )
    user_votes = {}
    user_post_id_list = list()
    #todo: cache this query set, but again takes only 3ms!
    if request.user.is_authenticated():
        user_votes = Vote.objects.filter(
                            user=request.user,
                            voted_post__id__in = post_to_author.keys()
                        ).values_list('voted_post_id', 'vote')
        user_votes = dict(user_votes)
        #we can avoid making this query by iterating through
        #already loaded posts
        user_post_id_list = [
            post_id for post_id in post_to_author if post_to_author[post_id] == request.user.id
        ]

    #resolve page number and comment number for permalinks
    show_comment_position = None
    if show_comment:
        show_page = show_comment.get_page_number(answer_posts=answers)
        show_comment_position = show_comment.get_order_number()
    elif show_answer:
        show_page = show_post.get_page_number(answer_posts=answers)

    objects_list = Paginator(answers, const.ANSWERS_PAGE_SIZE)
    if show_page > objects_list.num_pages:
        return HttpResponseRedirect(question_post.get_absolute_url())
    page_objects = objects_list.page(show_page)

    #count visits
    signals.question_visited.send(None,
                    request=request,
                    question=question_post,
                )

    paginator_data = {
        'is_paginated' : (objects_list.count > const.ANSWERS_PAGE_SIZE),
        'pages': objects_list.num_pages,
        'current_page_number': show_page,
        'page_object': page_objects,
        'base_url' : request.path + '?sort=%s&' % answer_sort_method,
    }
    paginator_context = functions.setup_paginator(paginator_data)

    #todo: maybe consolidate all activity in the thread
    #for the user into just one query?
    favorited = thread.has_favorite_by_user(request.user)

    is_cacheable = True
    if show_page != 1:
        is_cacheable = False
    elif show_comment_position > askbot_settings.MAX_COMMENTS_TO_SHOW:
        is_cacheable = False

    #maybe load draft
    initial = {}
    if request.user.is_authenticated():
        #todo: refactor into methor on thread
        drafts = models.DraftAnswer.objects.filter(
                                        author=request.user,
                                        thread=thread
                                    )
        if drafts.count() > 0:
            initial['text'] = drafts[0].get_text()

    custom_answer_form_path = django_settings.ASKBOT_NEW_ANSWER_FORM
    if custom_answer_form_path:
        answer_form_class = load_module(custom_answer_form_path)
    else:
        answer_form_class = AnswerForm

    answer_form = answer_form_class(initial=initial, user=request.user)

    user_can_post_comment = (
        request.user.is_authenticated() \
        and request.user.can_post_comment(question_post)
    )

    new_answer_allowed = True
    previous_answer = None
    if request.user.is_authenticated():
        if askbot_settings.LIMIT_ONE_ANSWER_PER_USER:
            for answer in answers:
                if answer.author_id == request.user.pk:
                    new_answer_allowed = False
                    previous_answer = answer
                    break

    if request.user.is_authenticated() and askbot_settings.GROUPS_ENABLED:
        group_read_only = request.user.is_read_only()
    else:
        group_read_only = False

    #session variable added so that the session is
    #not empty and is not autodeleted, otherwise anonymous
    #answer posting is impossible
    request.session['askbot_write_intent'] = True

    data = {
        'active_tab': 'questions',
        'answer' : answer_form,
        'answers' : page_objects.object_list,
        'answer_count': thread.get_answer_count(request.user),
        'blank_comment': MockPost(post_type='comment', author=request.user),#data for the js comment template
        'category_tree_data': askbot_settings.CATEGORY_TREE,
        'favorited' : favorited,
        'group_read_only': group_read_only,
        'is_cacheable': False,#is_cacheable, #temporary, until invalidation fix
        'language_code': translation.get_language(),
        'long_time': const.LONG_TIME,#"forever" caching
        'new_answer_allowed': new_answer_allowed,
        'oldest_answer_id': thread.get_oldest_answer_id(request.user),
        'page_class': 'question-page',
        'paginator_context' : paginator_context,
        'previous_answer': previous_answer,
        'published_answer_ids': published_answer_ids,
        'question' : question_post,
        'show_comment': show_comment,
        'show_comment_position': show_comment_position,
        'show_post': show_post,
        'similar_threads' : thread.get_similar_threads(),
        'tab_id' : answer_sort_method,
        'thread': thread,
        'thread_is_moderated': thread.is_moderated(),
        'user_is_thread_moderator': thread.has_moderator(request.user),
        'user_votes': user_votes,
        'user_post_id_list': user_post_id_list,
        'user_can_post_comment': user_can_post_comment,#in general
    }
    #shared with ...
    if askbot_settings.GROUPS_ENABLED:
        data['sharing_info'] = thread.get_sharing_info()

    data.update(context.get_for_tag_editor())

    extra = context.get_extra('ASKBOT_QUESTION_PAGE_EXTRA_CONTEXT', request, data)
    data.update(extra)

    return render(request, 'question.html', data)
Пример #9
0
        'similar_threads' : thread.get_similar_threads(),
        'tab_id' : answer_sort_method,
        'thread': thread,
        'thread_is_moderated': thread.is_moderated(),
        'user_is_thread_moderator': thread.has_moderator(request.user),
        'user_votes': user_votes,
        'user_post_id_list': user_post_id_list,
        'user_can_post_comment': user_can_post_comment,#in general
    }
    #shared with ...
    if askbot_settings.GROUPS_ENABLED:
        data['sharing_info'] = thread.get_sharing_info()

    data.update(context.get_for_tag_editor())

    extra = context.get_extra('ASKBOT_QUESTION_PAGE_EXTRA_CONTEXT', request, data)
    data.update(extra)

    return render(request, 'question.html', data)
    #print 'generated in ', timezone.now() - before
    #return res

def revisions(request, id, post_type = None):
    assert post_type in ('question', 'answer')
    post = get_object_or_404(models.Post, post_type=post_type, id=id)

    if post.deleted:
        if request.user.is_anonymous() \
            or not request.user.is_administrator_or_moderator():
            raise Http404
Пример #10
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, DEFAULT_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)
Пример #11
0
def question(request, id):  # refactor - long subroutine. display question body, answers and comments
    """view that displays body of the question and
    all answers to it

    TODO: convert this view into class
    """
    # process url parameters
    # TODO: fix inheritance of sort method from questions

    form = ShowQuestionForm(dict(tuple(request.POST.items()) + tuple(request.GET.items())))

    form.full_clean()  # always valid
    show_answer = form.cleaned_data['show_answer']
    show_comment = form.cleaned_data['show_comment']
    show_page = form.cleaned_data['show_page']
    answer_sort_method = form.cleaned_data['answer_sort_method']

    # load question and maybe refuse showing deleted question
    # if the question does not exist - try mapping to old questions
    # and and if it is not found again - then give up

    qs = Post.objects.filter(post_type='question').select_related('thread')

    question_post = qs.filter(id=id).first()
    if question_post is None:
        # Handle URL mapping - from old Q/A/C/ URLs to the new one
        question_post = qs.filter(old_question_id=id).first()
        if question_post is None:
            raise Http404

        if show_answer:
            try:
                old_answer = Post.objects.get_answers().get(old_answer_id=show_answer)
            except Post.DoesNotExist:
                pass
            else:
                return redirect(old_answer)

        elif show_comment:
            try:
                old_comment = Post.objects.get_comments().get(old_comment_id=show_comment)
            except Post.DoesNotExist:
                pass
            else:
                return redirect(old_comment)

    if show_comment or show_answer:
        try:
            show_post = Post.objects.get(pk=(show_comment or show_answer))
        except Post.DoesNotExist:
            # missing target post will be handled later
            pass
        else:
            if (show_comment and not show_post.is_comment()) or \
                    (show_answer and not show_post.is_answer()):
                return redirect(show_post)

    try:
        question_post.assert_is_visible_to(request.user)
    except exceptions.QuestionHidden as error:
        traceback.print_exc()
        # request.user.message_set.create(message=force_text(error))
        django_messages.info(request, force_text(error))
        return redirect('index')

    # redirect if slug in the url is wrong
    if request.path.split('/')[-2] != question_post.slug:
        logging.debug('no slug match!')
        lang = translation.get_language()
        question_url = question_post.get_absolute_url(language=lang)
        if request.GET:
            question_url += '?' + urlencode(request.GET)
        return redirect(question_url)

    # resolve comment and answer permalinks
    # they go first because in theory both can be moved to another question
    # this block "returns" show_post and assigns actual comment and answer
    # to show_comment and show_answer variables
    # in the case if the permalinked items or their parents are gone - redirect
    # redirect also happens if id of the object's origin post != requested id
    show_post = None  # used for permalinks
    if show_comment:
        # if url calls for display of a specific comment,
        # check that comment exists, that it belongs to
        # the current question
        # if it is an answer comment and the answer is hidden -
        # redirect to the default view of the question
        # if the question is hidden - redirect to the main page
        # in addition - if url points to a comment and the comment
        # is for the answer - we need the answer object
        try:
            show_comment = Post.objects.get_comments().get(id=show_comment)
        except Post.DoesNotExist as e:
            traceback.print_exc()
            error_message = _(
                'Sorry, the comment you are looking for has been '
                'deleted and is no longer accessible'
            )
            # request.user.message_set.create(message=error_message)
            django_messages.info(request, error_message)
            return redirect(question_post.thread)

        if str(show_comment.thread._question_post().id) != str(id):
            return redirect(show_comment)
        show_post = show_comment.parent

        try:
            show_comment.assert_is_visible_to(request.user)
        except exceptions.AnswerHidden as e:
            traceback.print_exc()
            # request.user.message_set.create(message=force_text(e))
            django_messages.info(request, force_text(e))
            # use reverse function here because question is not yet loaded
            return redirect('question', id=id)
        except exceptions.QuestionHidden as e:
            traceback.print_exc()
            # request.user.message_set.create(message=force_text(e))
            django_messages.info(request, force_text(e))
            return redirect('index')

    elif show_answer:
        # if the url calls to view a particular answer to
        # question - we must check whether the question exists
        # whether answer is actually corresponding to the current question
        # and that the visitor is allowed to see it
        show_post = get_object_or_404(Post, post_type='answer', id=show_answer)
        if str(show_post.thread._question_post().id) != str(id):
            return redirect(show_post)

        try:
            show_post.assert_is_visible_to(request.user)
        except django_exceptions.PermissionDenied as e:
            traceback.print_exc()
            # request.user.message_set.create(message=force_text(e))
            django_messages.info(request, force_text(e))
            return redirect('question', id=id)

    thread = question_post.thread

    logging.debug('answer_sort_method=' + force_text(answer_sort_method))

    # load answers and post id's->athor_id mapping
    # posts are pre-stuffed with the correctly ordered comments
    question_post, answers, post_to_author, published_answer_ids = thread.get_post_data_for_question_view(
        sort_method=answer_sort_method,
        user=request.user)
    user_votes = {}
    user_post_id_list = list()

    # TODO: cache this query set, but again takes only 3ms!
    if request.user.is_authenticated():
        user_votes = Vote.objects.\
            filter(user=request.user, voted_post__id__in=post_to_author.keys()).\
            values_list('voted_post_id', 'vote')
        user_votes = dict(user_votes)
        # we can avoid making this query by iterating through
        # already loaded posts
        user_post_id_list = [
            post_id for post_id in post_to_author if post_to_author[post_id] == request.user.id
        ]

    # resolve page number and comment number for permalinks
    show_comment_position = None
    if show_comment:
        show_page = show_comment.get_page_number(answer_posts=answers)
        show_comment_position = show_comment.get_order_number()
    elif show_answer:
        show_page = show_post.get_page_number(answer_posts=answers)

    objects_list = Paginator(answers, const.ANSWERS_PAGE_SIZE)
    if show_page > objects_list.num_pages:
        return redirect(question_post)
    page_objects = objects_list.page(show_page)

    # count visits
    signals.question_visited.send(None, request=request, question=question_post)

    paginator_data = {
        'is_paginated': (objects_list.count > const.ANSWERS_PAGE_SIZE),
        'pages': objects_list.num_pages,
        'current_page_number': show_page,
        'page_object': page_objects,
        'base_url': request.path + '?sort=%s&' % answer_sort_method,
    }
    paginator_context = functions.setup_paginator(paginator_data)

    # TODO: maybe consolidate all activity in the thread
    # for the user into just one query?
    favorited = thread.has_favorite_by_user(request.user)

    is_cacheable = True
    if show_page != 1:
        is_cacheable = False
    elif (show_comment_position or 0) > askbot_settings.MAX_COMMENTS_TO_SHOW:
        is_cacheable = False

    # maybe load draft
    initial = {}
    if request.user.is_authenticated():
        # TODO: refactor into methor on thread
        drafts = DraftAnswer.objects.filter(author=request.user, thread=thread)
        if drafts.count() > 0:
            initial['text'] = drafts[0].text

    custom_answer_form_path = getattr(django_settings, 'ASKBOT_NEW_ANSWER_FORM', None)
    if custom_answer_form_path:
        answer_form_class = load_module(custom_answer_form_path)
    else:
        answer_form_class = AnswerForm

    answer_form = answer_form_class(initial=initial, user=request.user)

    user_can_post_comment = (request.user.is_authenticated() and request.user.can_post_comment(question_post))

    new_answer_allowed = True
    previous_answer = None
    if request.user.is_authenticated():
        if askbot_settings.LIMIT_ONE_ANSWER_PER_USER:
            for answer in answers:
                if answer.author_id == request.user.pk:
                    new_answer_allowed = False
                    previous_answer = answer
                    break

    if request.user.is_authenticated() and askbot_settings.GROUPS_ENABLED:
        group_read_only = request.user.is_read_only()
    else:
        group_read_only = False

    data = {
        'active_tab': 'questions',
        'answer': answer_form,
        'answers': page_objects.object_list,
        'answer_count': thread.get_answer_count(request.user),
        'blank_comment': MockPost(post_type='comment', author=request.user),  # data for the js comment template
        'category_tree_data': askbot_settings.CATEGORY_TREE,
        'editor_is_unfolded': answer_form.has_data(),
        'favorited': favorited,
        'group_read_only': group_read_only,
        'is_cacheable': False,  # is_cacheable, # temporary, until invalidation fix
        'language_code': translation.get_language(),
        'long_time': const.LONG_TIME,  # "forever" caching
        'new_answer_allowed': new_answer_allowed,
        'oldest_answer_id': thread.get_oldest_answer_id(request.user),
        'page_class': 'question-page',
        'paginator_context': paginator_context,
        'previous_answer': previous_answer,
        'published_answer_ids': published_answer_ids,
        'question': question_post,
        'show_comment': show_comment,
        'show_comment_position': show_comment_position,
        'show_post': show_post,
        'similar_threads': thread.get_similar_threads(),
        'tab_id': answer_sort_method,
        'thread': thread,
        'thread_is_moderated': thread.is_moderated(),
        'user_is_thread_moderator': thread.has_moderator(request.user),
        'user_votes': user_votes,
        'user_post_id_list': user_post_id_list,
        'user_can_post_comment': user_can_post_comment,  # in general
    }

    # shared with ...
    if askbot_settings.GROUPS_ENABLED:
        data['sharing_info'] = thread.get_sharing_info()

    data.update(context.get_for_tag_editor())

    extra = context.get_extra('ASKBOT_QUESTION_PAGE_EXTRA_CONTEXT', request, data)
    data.update(extra)

    return render(request, 'question.jinja', data)
Пример #12
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,
    }

    # 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' % (
        django_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

        #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'],
        }
        ajax_data['related_tags'] = [{
            'name':
            escape(tag.name),
            'used_count':
            humanize.intcomma(tag.local_used_count)
        } for tag in related_tags]

        #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 = reverse('group_settings',
                              kwargs={'group': 'QA_SITE_SETTINGS'})
                url = url + '#id_QA_SITE_SETTINGS__APP_URL'
                msg = _(
                    'Please go to '
                    '<a href="%s">"settings->URLs, keywords and greetings"</a> '
                    '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)
Пример #13
0
def user_stats(request, user, context):
    question_filter = {}
    if request.user != user:
        question_filter["is_anonymous"] = False

    if askbot_settings.ENABLE_CONTENT_MODERATION:
        question_filter["approved"] = True

    #
    # Questions
    #
    questions = (
        user.posts.get_questions(user=request.user)
        .filter(**question_filter)
        .order_by("-points", "-thread__last_activity_at")
        .select_related("thread", "thread__last_activity_by")[:100]
    )

    # added this if to avoid another query if questions is less than 100
    if len(questions) < 100:
        question_count = len(questions)
    else:
        question_count = user.posts.get_questions().filter(**question_filter).count()

    #
    # Top answers
    #
    top_answers = (
        user.posts.get_answers(request.user)
        .filter(deleted=False, thread__posts__deleted=False, thread__posts__post_type="question")
        .select_related("thread")
        .order_by("-points", "-added_at")[:100]
    )

    top_answer_count = len(top_answers)
    #
    # Votes
    #
    up_votes = models.Vote.objects.get_up_vote_count_from_user(user)
    down_votes = models.Vote.objects.get_down_vote_count_from_user(user)
    votes_today = models.Vote.objects.get_votes_count_today_from_user(user)
    votes_total = askbot_settings.MAX_VOTES_PER_USER_PER_DAY

    #
    # Tags
    #
    # INFO: There's bug in Django that makes the following query kind of broken (GROUP BY clause is problematic):
    #       http://stackoverflow.com/questions/7973461/django-aggregation-does-excessive-group-by-clauses
    #       Fortunately it looks like it returns correct results for the test data
    user_tags = (
        models.Tag.objects.filter(threads__posts__author=user)
        .distinct()
        .annotate(user_tag_usage_count=Count("threads"))
        .order_by("-user_tag_usage_count")[: const.USER_VIEW_DATA_SIZE]
    )
    user_tags = list(user_tags)  # evaluate

    when = askbot_settings.MARKED_TAGS_ARE_PUBLIC_WHEN
    if when == "always" or (when == "when-user-wants" and user.show_marked_tags == True):
        # refactor into: user.get_marked_tag_names('good'/'bad'/'subscribed')
        interesting_tag_names = user.get_marked_tag_names("good")
        ignored_tag_names = user.get_marked_tag_names("bad")
        subscribed_tag_names = user.get_marked_tag_names("subscribed")
    else:
        interesting_tag_names = None
        ignored_tag_names = None
        subscribed_tag_names = None

    #    tags = models.Post.objects.filter(author=user).values('id', 'thread', 'thread__tags')
    #    post_ids = set()
    #    thread_ids = set()
    #    tag_ids = set()
    #    for t in tags:
    #        post_ids.add(t['id'])
    #        thread_ids.add(t['thread'])
    #        tag_ids.add(t['thread__tags'])
    #        if t['thread__tags'] == 11:
    #            print t['thread'], t['id']
    #    import ipdb; ipdb.set_trace()

    #
    # Badges/Awards (TODO: refactor into Managers/QuerySets when a pattern emerges; Simplify when we get rid of Question&Answer models)
    #
    post_type = ContentType.objects.get_for_model(models.Post)

    user_awards = models.Award.objects.filter(user=user).select_related("badge")

    awarded_post_ids = []
    for award in user_awards:
        if award.content_type_id == post_type.id:
            awarded_post_ids.append(award.object_id)

    awarded_posts = models.Post.objects.filter(id__in=awarded_post_ids).select_related(
        "thread"
    )  # select related to avoid additional queries in Post.get_absolute_url()

    awarded_posts_map = {}
    for post in awarded_posts:
        awarded_posts_map[post.id] = post

    badges_dict = collections.defaultdict(list)

    for award in user_awards:
        # Fetch content object
        if award.content_type_id == post_type.id:
            # here we go around a possibility of awards
            # losing the content objects when the content
            # objects are deleted for some reason
            awarded_post = awarded_posts_map.get(award.object_id, None)
            if awarded_post is not None:
                # protect from awards that are associated with deleted posts
                award.content_object = awarded_post
                award.content_object_is_post = True
            else:
                award.content_object_is_post = False
        else:
            award.content_object_is_post = False

        # "Assign" to its Badge
        badges_dict[award.badge].append(award)

    badges = badges_dict.items()
    badges.sort(key=operator.itemgetter(1), reverse=True)

    user_groups = models.Group.objects.get_for_user(user=user)
    user_groups = user_groups.exclude_personal()
    global_group = models.Group.objects.get_global_group()
    user_groups = user_groups.exclude(name=global_group.name)

    if request.user == user:
        groups_membership_info = user.get_groups_membership_info(user_groups)
    else:
        groups_membership_info = collections.defaultdict()

    data = {
        "active_tab": "users",
        "page_class": "user-profile-page",
        "support_custom_avatars": ("avatar" in django_settings.INSTALLED_APPS),
        "tab_name": "stats",
        "tab_description": _("user profile"),
        "page_title": _("user profile overview"),
        "user_status_for_display": user.get_status_display(soft=True),
        "questions": questions,
        "question_count": question_count,
        "top_answers": top_answers,
        "top_answer_count": top_answer_count,
        "up_votes": up_votes,
        "down_votes": down_votes,
        "total_votes": up_votes + down_votes,
        "votes_today_left": votes_total - votes_today,
        "votes_total_per_day": votes_total,
        "user_tags": user_tags,
        "user_groups": user_groups,
        "groups_membership_info": groups_membership_info,
        "interesting_tag_names": interesting_tag_names,
        "ignored_tag_names": ignored_tag_names,
        "subscribed_tag_names": subscribed_tag_names,
        "badges": badges,
        "total_badges": len(badges),
    }
    context.update(data)

    extra_context = view_context.get_extra("ASKBOT_USER_PROFILE_PAGE_EXTRA_CONTEXT", request, context)
    context.update(extra_context)

    return render(request, "user_profile/user_stats.html", context)
Пример #14
0
def user_stats(request, user, context):
    question_filter = {}
    if request.user != user:
        question_filter['is_anonymous'] = False

    if askbot_settings.CONTENT_MODERATION_MODE == 'premoderation':
        question_filter['approved'] = True

    #
    # Questions
    #
    questions_qs = user.posts.get_questions(
                    user=request.user
                ).filter(
                    **question_filter
                ).order_by(
                    '-points', '-thread__last_activity_at'
                ).select_related(
                    'thread', 'thread__last_activity_by'
                )

    q_paginator = Paginator(questions_qs, const.USER_POSTS_PAGE_SIZE)
    questions = q_paginator.page(1).object_list
    question_count = q_paginator.count

    q_paginator_context = functions.setup_paginator({
                    'is_paginated' : (question_count > const.USER_POSTS_PAGE_SIZE),
                    'pages': q_paginator.num_pages,
                    'current_page_number': 1,
                    'page_object': q_paginator.page(1),
                    'base_url' : '?' #this paginator will be ajax
                })
    #
    # Top answers
    #
    a_paginator = user.get_top_answers_paginator(request.user)
    top_answers = a_paginator.page(1).object_list
    top_answer_count = a_paginator.count

    a_paginator_context = functions.setup_paginator({
                    'is_paginated' : (top_answer_count > const.USER_POSTS_PAGE_SIZE),
                    'pages': a_paginator.num_pages,
                    'current_page_number': 1,
                    'page_object': a_paginator.page(1),
                    'base_url' : '?' #this paginator will be ajax
                })
    #
    # Votes
    #
    up_votes = models.Vote.objects.get_up_vote_count_from_user(user)
    down_votes = models.Vote.objects.get_down_vote_count_from_user(user)
    votes_today = models.Vote.objects.get_votes_count_today_from_user(user)
    votes_total = askbot_settings.MAX_VOTES_PER_USER_PER_DAY

    #
    # Tags
    #
    # INFO: There's bug in Django that makes the following query kind of broken (GROUP BY clause is problematic):
    #       http://stackoverflow.com/questions/7973461/django-aggregation-does-excessive-group-by-clauses
    #       Fortunately it looks like it returns correct results for the test data
    user_tags = models.Tag.objects.filter(
                                    threads__posts__author=user,
                                    language_code=get_language()
                                ).distinct().\
                    annotate(user_tag_usage_count=Count('threads')).\
                    order_by('-user_tag_usage_count')[:const.USER_VIEW_DATA_SIZE]
    user_tags = list(user_tags) # evaluate

    when = askbot_settings.MARKED_TAGS_ARE_PUBLIC_WHEN
    if when == 'always' or \
        (when == 'when-user-wants' and user.show_marked_tags == True):
        #refactor into: user.get_marked_tag_names('good'/'bad'/'subscribed')
        interesting_tag_names = user.get_marked_tag_names('good')
        ignored_tag_names = user.get_marked_tag_names('bad')
        subscribed_tag_names = user.get_marked_tag_names('subscribed')
    else:
        interesting_tag_names = None
        ignored_tag_names = None
        subscribed_tag_names = None

#    tags = models.Post.objects.filter(author=user).values('id', 'thread', 'thread__tags')
#    post_ids = set()
#    thread_ids = set()
#    tag_ids = set()
#    for t in tags:
#        post_ids.add(t['id'])
#        thread_ids.add(t['thread'])
#        tag_ids.add(t['thread__tags'])
#        if t['thread__tags'] == 11:
#            print t['thread'], t['id']
#    import ipdb; ipdb.set_trace()

    #
    # Badges/Awards (TODO: refactor into Managers/QuerySets when a pattern emerges; Simplify when we get rid of Question&Answer models)
    #
    post_type = ContentType.objects.get_for_model(models.Post)

    user_awards = models.Award.objects.filter(user=user).select_related('badge')

    awarded_post_ids = []
    for award in user_awards:
        if award.content_type_id == post_type.id:
            awarded_post_ids.append(award.object_id)

    awarded_posts = models.Post.objects.filter(id__in=awarded_post_ids)\
                    .select_related('thread') # select related to avoid additional queries in Post.get_absolute_url()

    awarded_posts_map = {}
    for post in awarded_posts:
        awarded_posts_map[post.id] = post

    badges_dict = collections.defaultdict(list)

    for award in user_awards:
        if award.badge.is_enabled() == False:
            continue

        # Fetch content object
        if award.content_type_id == post_type.id:
            #here we go around a possibility of awards
            #losing the content objects when the content
            #objects are deleted for some reason
            awarded_post = awarded_posts_map.get(award.object_id, None)
            if awarded_post is not None:
                #protect from awards that are associated with deleted posts
                award.content_object = awarded_post
                award.content_object_is_post = True
            else:
                award.content_object_is_post = False
        else:
            award.content_object_is_post = False

        # "Assign" to its Badge
        badges_dict[award.badge].append(award)

    badges = badges_dict.items()
    badges.sort(key=operator.itemgetter(1), reverse=True)

    user_groups = models.Group.objects.get_for_user(user = user)
    user_groups = user_groups.exclude_personal()
    global_group = models.Group.objects.get_global_group()
    user_groups = user_groups.exclude(name=global_group.name)

    if request.user.pk == user.pk:
        groups_membership_info = user.get_groups_membership_info(user_groups)
    else:
        groups_membership_info = collections.defaultdict()

    data = {
        'active_tab':'users',
        'page_class': 'user-profile-page',
        'support_custom_avatars': ('avatar' in django_settings.INSTALLED_APPS),
        'tab_name' : 'stats',
        'page_title' : _('user profile overview'),
        'questions' : questions,
        'question_count': question_count,
        'q_paginator_context': q_paginator_context,

        'top_answers': top_answers,
        'top_answer_count': top_answer_count,
        'a_paginator_context': a_paginator_context,
        'page_size': const.USER_POSTS_PAGE_SIZE,

        'up_votes' : up_votes,
        'down_votes' : down_votes,
        'total_votes': up_votes + down_votes,
        'votes_today_left': votes_total - votes_today,
        'votes_total_per_day': votes_total,

        'user_tags' : user_tags,
        'user_groups': user_groups,
        'groups_membership_info': groups_membership_info,
        'interesting_tag_names': interesting_tag_names,
        'ignored_tag_names': ignored_tag_names,
        'subscribed_tag_names': subscribed_tag_names,
        'badges': badges,
        'total_badges' : len(badges),
    }
    context.update(data)

    extra_context = view_context.get_extra(
                                'ASKBOT_USER_PROFILE_PAGE_EXTRA_CONTEXT',
                                request,
                                context
                            )
    context.update(extra_context)

    return render(request, 'user_profile/user_stats.html', context)
Пример #15
0
def user_stats(request, user, context):
    question_filter = {}
    if request.user != user:
        question_filter['is_anonymous'] = False

    if askbot_settings.CONTENT_MODERATION_MODE == 'premoderation':
        question_filter['approved'] = True

    #
    # Questions
    #
    questions_qs = user.posts.get_questions(
                    user=request.user
                ).filter(
                    **question_filter
                ).order_by(
                    '-points', '-thread__last_activity_at'
                ).select_related(
                    'thread', 'thread__last_activity_by'
                )

    q_paginator = Paginator(questions_qs, const.USER_POSTS_PAGE_SIZE)
    questions = q_paginator.page(1).object_list
    question_count = q_paginator.count

    q_paginator_context = functions.setup_paginator({
                    'is_paginated' : (question_count > const.USER_POSTS_PAGE_SIZE),
                    'pages': q_paginator.num_pages,
                    'current_page_number': 1,
                    'page_object': q_paginator.page(1),
                    'base_url' : '?' #this paginator will be ajax
                })
    #
    # Top answers
    #
    a_paginator = user.get_top_answers_paginator(request.user)
    top_answers = a_paginator.page(1).object_list
    top_answer_count = a_paginator.count

    a_paginator_context = functions.setup_paginator({
                    'is_paginated' : (top_answer_count > const.USER_POSTS_PAGE_SIZE),
                    'pages': a_paginator.num_pages,
                    'current_page_number': 1,
                    'page_object': a_paginator.page(1),
                    'base_url' : '?' #this paginator will be ajax
                })
    #
    # Votes
    #
    up_votes = models.Vote.objects.get_up_vote_count_from_user(user)
    down_votes = models.Vote.objects.get_down_vote_count_from_user(user)
    votes_today = models.Vote.objects.get_votes_count_today_from_user(user)
    votes_total = askbot_settings.MAX_VOTES_PER_USER_PER_DAY

    #
    # Tags
    #
    # INFO: There's bug in Django that makes the following query kind of broken (GROUP BY clause is problematic):
    #       http://stackoverflow.com/questions/7973461/django-aggregation-does-excessive-group-by-clauses
    #       Fortunately it looks like it returns correct results for the test data
    user_tags = models.Tag.objects.filter(
                                    threads__posts__author=user,
                                    language_code=get_language()
                                ).distinct().\
                    annotate(user_tag_usage_count=Count('threads')).\
                    order_by('-user_tag_usage_count')[:const.USER_VIEW_DATA_SIZE]
    user_tags = list(user_tags) # evaluate

    when = askbot_settings.MARKED_TAGS_ARE_PUBLIC_WHEN
    if when == 'always' or \
        (when == 'when-user-wants' and user.show_marked_tags == True):
        #refactor into: user.get_marked_tag_names('good'/'bad'/'subscribed')
        interesting_tag_names = user.get_marked_tag_names('good')
        ignored_tag_names = user.get_marked_tag_names('bad')
        subscribed_tag_names = user.get_marked_tag_names('subscribed')
    else:
        interesting_tag_names = None
        ignored_tag_names = None
        subscribed_tag_names = None

#    tags = models.Post.objects.filter(author=user).values('id', 'thread', 'thread__tags')
#    post_ids = set()
#    thread_ids = set()
#    tag_ids = set()
#    for t in tags:
#        post_ids.add(t['id'])
#        thread_ids.add(t['thread'])
#        tag_ids.add(t['thread__tags'])
#        if t['thread__tags'] == 11:
#            print t['thread'], t['id']
#    import ipdb; ipdb.set_trace()

    #
    # Badges/Awards (TODO: refactor into Managers/QuerySets when a pattern emerges; Simplify when we get rid of Question&Answer models)
    #
    post_type = ContentType.objects.get_for_model(models.Post)

    user_awards = models.Award.objects.filter(user=user).select_related('badge')

    awarded_post_ids = []
    for award in user_awards:
        if award.content_type_id == post_type.id:
            awarded_post_ids.append(award.object_id)

    awarded_posts = models.Post.objects.filter(id__in=awarded_post_ids)\
                    .select_related('thread') # select related to avoid additional queries in Post.get_absolute_url()

    awarded_posts_map = {}
    for post in awarded_posts:
        awarded_posts_map[post.id] = post

    badges_dict = collections.defaultdict(list)

    for award in user_awards:
        # Fetch content object
        if award.content_type_id == post_type.id:
            #here we go around a possibility of awards
            #losing the content objects when the content
            #objects are deleted for some reason
            awarded_post = awarded_posts_map.get(award.object_id, None)
            if awarded_post is not None:
                #protect from awards that are associated with deleted posts
                award.content_object = awarded_post
                award.content_object_is_post = True
            else:
                award.content_object_is_post = False
        else:
            award.content_object_is_post = False

        # "Assign" to its Badge
        badges_dict[award.badge].append(award)

    badges = badges_dict.items()
    badges.sort(key=operator.itemgetter(1), reverse=True)

    user_groups = models.Group.objects.get_for_user(user = user)
    user_groups = user_groups.exclude_personal()
    global_group = models.Group.objects.get_global_group()
    user_groups = user_groups.exclude(name=global_group.name)

    if request.user == user:
        groups_membership_info = user.get_groups_membership_info(user_groups)
    else:
        groups_membership_info = collections.defaultdict()

    data = {
        'active_tab':'users',
        'page_class': 'user-profile-page',
        'support_custom_avatars': ('avatar' in django_settings.INSTALLED_APPS),
        'tab_name' : 'stats',
        'page_title' : _('user profile overview'),
        'questions' : questions,
        'question_count': question_count,
        'q_paginator_context': q_paginator_context,

        'top_answers': top_answers,
        'top_answer_count': top_answer_count,
        'a_paginator_context': a_paginator_context,
        'page_size': const.USER_POSTS_PAGE_SIZE,

        'up_votes' : up_votes,
        'down_votes' : down_votes,
        'total_votes': up_votes + down_votes,
        'votes_today_left': votes_total - votes_today,
        'votes_total_per_day': votes_total,

        'user_tags' : user_tags,
        'user_groups': user_groups,
        'groups_membership_info': groups_membership_info,
        'interesting_tag_names': interesting_tag_names,
        'ignored_tag_names': ignored_tag_names,
        'subscribed_tag_names': subscribed_tag_names,
        'badges': badges,
        'total_badges' : len(badges),
    }
    context.update(data)

    extra_context = view_context.get_extra(
                                'ASKBOT_USER_PROFILE_PAGE_EXTRA_CONTEXT',
                                request,
                                context
                            )
    context.update(extra_context)

    return render(request, 'user_profile/user_stats.html', context)
Пример #16
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)
Пример #17
0
def edit_answer(request, id):
    answer = get_object_or_404(models.Post, id=id)
    revision = answer.get_latest_revision()

    class_path = getattr(settings, 'ASKBOT_EDIT_ANSWER_FORM', None)
    if class_path:
        edit_answer_form_class = load_module(class_path)
    else:
        edit_answer_form_class = forms.EditAnswerForm

    try:
        request.user.assert_can_edit_answer(answer)
        if request.method == "POST":
            if request.POST['select_revision'] == 'true':
                # user has changed revistion number
                revision_form = forms.RevisionForm(answer, revision,
                                                   request.POST)
                if revision_form.is_valid():
                    # Replace with those from the selected revision
                    rev = revision_form.cleaned_data['revision']
                    revision = answer.revisions.get(revision=rev)
                    form = edit_answer_form_class(answer,
                                                  revision,
                                                  user=request.user)
                else:
                    form = edit_answer_form_class(answer,
                                                  revision,
                                                  request.POST,
                                                  user=request.user)
            else:
                form = edit_answer_form_class(answer,
                                              revision,
                                              request.POST,
                                              user=request.user)
                revision_form = forms.RevisionForm(answer, revision)

                if form.is_valid():
                    if form.has_changed():
                        user = form.get_post_user(request.user)
                        suppress_email = form.cleaned_data['suppress_email']
                        is_private = form.cleaned_data.get(
                            'post_privately', False)
                        user.edit_answer(
                            answer=answer,
                            body_text=form.cleaned_data['text'],
                            revision_comment=form.cleaned_data['summary'],
                            wiki=form.cleaned_data.get('wiki', answer.wiki),
                            is_private=is_private,
                            suppress_email=suppress_email)

                        signals.answer_edited.send(None,
                                                   answer=answer,
                                                   user=user,
                                                   form_data=form.cleaned_data)

                    return HttpResponseRedirect(answer.get_absolute_url())
        else:
            revision_form = forms.RevisionForm(answer, revision)
            form = edit_answer_form_class(answer, revision, user=request.user)
            if request.user.can_make_group_private_posts():
                form.initial['post_privately'] = answer.is_private()

        data = {
            'page_class': 'edit-answer-page',
            'active_tab': 'questions',
            'answer': answer,
            'revision': revision,
            'revision_form': revision_form,
            'form': form,
        }
        extra_context = context.get_extra(
            'ASKBOT_EDIT_ANSWER_PAGE_EXTRA_CONTEXT', request, data)
        data.update(extra_context)

        return render(request, 'answer_edit.html', data)

    except exceptions.PermissionDenied, e:
        request.user.message_set.create(message=unicode(e))
        return HttpResponseRedirect(answer.get_absolute_url())
Пример #18
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)
Пример #19
0
            '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(),
            'update_avatar_data': schedules.should_update_avatar_data(request),
            '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)

        return render(request, 'main_page.html', template_data)


def tags(request):#view showing a listing of available tags - plain list

    #1) Get parameters. This normally belongs to form cleaning.
    post_data = request.GET
    sortby = post_data.get('sort', 'used')
    try:
        page = int(post_data.get('page', '1'))
    except ValueError: