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)
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())
'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(
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&' % 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)
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&' % 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)
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())
def questions(request, **kwargs): """ List of Questions, Tagged questions, and Unanswered questions. matching search query or user selection """ #before = datetime.datetime.now() if request.method != 'GET': return HttpResponseNotAllowed(['GET']) search_state = SearchState( user_logged_in=request.user.is_authenticated(), **kwargs ) qs, meta_data = models.Thread.objects.run_advanced_search( request_user=request.user, search_state=search_state ) if meta_data['non_existing_tags']: search_state = search_state.remove_tags(meta_data['non_existing_tags']) paginator = Paginator(qs, search_state.page_size) if paginator.num_pages < search_state.page: search_state.page = 1 page = paginator.page(search_state.page) page.object_list = list(page.object_list) # evaluate the queryset # INFO: Because for the time being we need question posts and thread authors # down the pipeline, we have to precache them in thread objects models.Thread.objects.precache_view_data_hack(threads=page.object_list) related_tags = Tag.objects.get_related_to_search( threads=page.object_list, ignored_tag_names=meta_data.get('ignored_tag_names',[]) ) tag_list_type = askbot_settings.TAG_LIST_FORMAT if tag_list_type == 'cloud': #force cloud to sort by name related_tags = sorted(related_tags, key = operator.attrgetter('name')) contributors = list( models.Thread.objects.get_thread_contributors( thread_list=page.object_list ).only('id', 'username', 'gravatar') ) paginator_context = { 'is_paginated' : (paginator.count > search_state.page_size), 'pages': paginator.num_pages, 'current_page_number': search_state.page, 'page_object': page, 'base_url' : search_state.query_string(), 'page_size' : search_state.page_size, } #get url for the rss feed context_feed_url = reverse('latest_questions_feed') # We need to pass the rss feed url based # on the search state to the template. # We use QueryDict to get a querystring # from dicts and arrays. Much cleaner # than parsing and string formating. rss_query_dict = QueryDict("").copy() if search_state.query: # We have search string in session - pass it to # the QueryDict rss_query_dict.update({"q": search_state.query}) if search_state.tags: # We have tags in session - pass it to the # QueryDict but as a list - we want tags+ rss_query_dict.setlist('tags', search_state.tags) context_feed_url += '?' + rss_query_dict.urlencode() reset_method_count = len(filter(None, [search_state.query, search_state.tags, meta_data.get('author_name', None)])) if request.is_ajax(): q_count = paginator.count #todo: words question_counter = ungettext('%(q_num)s question', '%(q_num)s questions', q_count) question_counter = question_counter % {'q_num': humanize.intcomma(q_count),} if q_count > search_state.page_size: paginator_tpl = get_template('main_page/paginator.html') paginator_html = paginator_tpl.render( RequestContext( request, { 'context': paginator_context, 'questions_count': q_count, 'page_size' : search_state.page_size, 'search_state': search_state, } ) ) else: paginator_html = '' questions_tpl = get_template('main_page/questions_loop.html') questions_html = questions_tpl.render( RequestContext( request, { 'threads': page, 'search_state': search_state, 'reset_method_count': reset_method_count, 'request': request } ) ) ajax_data = { 'query_data': { 'tags': search_state.tags, 'sort_order': search_state.sort, 'ask_query_string': search_state.ask_query_string(), }, 'paginator': paginator_html, 'question_counter': question_counter, 'faces': [],#[extra_tags.gravatar(contributor, 48) for contributor in contributors], 'feed_url': context_feed_url, 'query_string': search_state.query_string(), 'page_size' : search_state.page_size, 'questions': questions_html.replace('\n',''), 'non_existing_tags': meta_data['non_existing_tags'], } related_tags_tpl = get_template('widgets/related_tags.html') related_tags_data = { 'tags': related_tags, 'tag_list_type': tag_list_type, 'query_string': search_state.query_string(), 'search_state': search_state, 'language_code': translation.get_language(), } if tag_list_type == 'cloud': related_tags_data['font_size'] = extra_tags.get_tag_font_size(related_tags) ajax_data['related_tags_html'] = related_tags_tpl.render( RequestContext(request, related_tags_data) ) #here we add and then delete some items #to allow extra context processor to work ajax_data['tags'] = related_tags ajax_data['interesting_tag_names'] = None ajax_data['threads'] = page extra_context = context.get_extra( 'ASKBOT_QUESTIONS_PAGE_EXTRA_CONTEXT', request, ajax_data ) del ajax_data['tags'] del ajax_data['interesting_tag_names'] del ajax_data['threads'] ajax_data.update(extra_context) return HttpResponse(simplejson.dumps(ajax_data), mimetype = 'application/json') else: # non-AJAX branch template_data = { 'active_tab': 'questions', 'author_name' : meta_data.get('author_name',None), 'contributors' : contributors, 'context' : paginator_context, 'is_unanswered' : False,#remove this from template 'interesting_tag_names': meta_data.get('interesting_tag_names', None), 'ignored_tag_names': meta_data.get('ignored_tag_names', None), 'subscribed_tag_names': meta_data.get('subscribed_tag_names', None), 'language_code': translation.get_language(), 'name_of_anonymous_user' : models.get_name_of_anonymous_user(), 'page_class': 'main-page', 'page_size': search_state.page_size, 'query': search_state.query, 'threads' : page, 'questions_count' : paginator.count, 'reset_method_count': reset_method_count, 'scope': search_state.scope, 'show_sort_by_relevance': conf.should_show_sort_by_relevance(), 'search_tags' : search_state.tags, 'sort': search_state.sort, 'tab_id' : search_state.sort, 'tags' : related_tags, 'tag_list_type' : tag_list_type, 'font_size' : extra_tags.get_tag_font_size(related_tags), 'display_tag_filter_strategy_choices': conf.get_tag_display_filter_strategy_choices(), 'email_tag_filter_strategy_choices': conf.get_tag_email_filter_strategy_choices(), 'query_string': search_state.query_string(), 'search_state': search_state, 'feed_url': context_feed_url } extra_context = context.get_extra( 'ASKBOT_QUESTIONS_PAGE_EXTRA_CONTEXT', request, template_data ) template_data.update(extra_context) template_data.update(context.get_for_tag_editor()) #and one more thing:) give admin user heads up about #setting the domain name if they have not done that yet #todo: move this out to a separate middleware if request.user.is_authenticated() and request.user.is_administrator(): if domain_is_bad(): url = askbot_settings.get_setting_url(('QA_SITE_SETTINGS', 'APP_URL')) msg = _( 'Please go to Settings -> %s ' 'and set the base url for your site to function properly' ) % url request.user.message_set.create(message=msg) return render(request, 'main_page.html', template_data)
def 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)
'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
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)
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)
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)
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)
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)
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)
def tags(request):#view showing a listing of available tags - plain list form = ShowTagsForm(request.REQUEST) form.full_clean() #always valid page = form.cleaned_data['page'] sort_method = form.cleaned_data['sort'] query = form.cleaned_data['query'] tag_list_type = askbot_settings.TAG_LIST_FORMAT #2) Get query set for the tags. query_params = { 'deleted': False, 'language_code': translation.get_language() } if query != '': query_params['name__icontains'] = query tags_qs = Tag.objects.filter(**query_params).exclude(used_count=0) if sort_method == 'name': order_by = 'name' else: order_by = '-used_count' tags_qs = tags_qs.order_by(order_by) #3) Start populating the template context. data = { 'active_tab': 'tags', 'page_class': 'tags-page', 'tag_list_type' : tag_list_type, 'query' : query, 'tab_id' : sort_method, 'keywords' : query, 'search_state': SearchState(*[None for x in range(8)]) } if tag_list_type == 'list': #plain listing is paginated objects_list = Paginator(tags_qs, const.TAGS_PAGE_SIZE) try: tags = objects_list.page(page) except (EmptyPage, InvalidPage): tags = objects_list.page(objects_list.num_pages) paginator_data = { 'is_paginated' : (objects_list.num_pages > 1), 'pages': objects_list.num_pages, 'current_page_number': page, 'page_object': tags, 'base_url' : reverse('tags') + '?sort=%s&' % sort_method } paginator_context = functions.setup_paginator(paginator_data) data['paginator_context'] = paginator_context else: #tags for the tag cloud are given without pagination tags = tags_qs font_size = extra_tags.get_tag_font_size(tags) data['font_size'] = font_size data['tags'] = tags data.update(context.get_extra('ASKBOT_TAGS_PAGE_EXTRA_CONTEXT', request, data)) if request.is_ajax(): template = get_template('tags/content.html') template_context = RequestContext(request, data) json_data = {'success': True, 'html': template.render(template_context)} json_string = simplejson.dumps(json_data) return HttpResponse(json_string, content_type='application/json') else: return render(request, 'tags.html', data)
def 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())
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)
'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: