def user_email_subscriptions(request, user, context): logging.debug(get_request_info(request)) if request.method == 'POST': email_feeds_form = forms.EditUserEmailFeedsForm(request.POST) tag_filter_form = forms.TagFilterSelectionForm(request.POST, instance=user) if email_feeds_form.is_valid() and tag_filter_form.is_valid(): action_status = None tag_filter_saved = tag_filter_form.save() if tag_filter_saved: action_status = _('changes saved') if 'save' in request.POST: feeds_saved = email_feeds_form.save(user) if feeds_saved: action_status = _('changes saved') elif 'stop_email' in request.POST: email_stopped = email_feeds_form.reset().save(user) initial_values = forms.EditUserEmailFeedsForm.NO_EMAIL_INITIAL email_feeds_form = forms.EditUserEmailFeedsForm(initial=initial_values) if email_stopped: action_status = _('email updates canceled') else: #user may have been created by some app that does not know #about the email subscriptions, in that case the call below #will add any subscription settings that are missing #using the default frequencies user.add_missing_askbot_subscriptions() #initialize the form email_feeds_form = forms.EditUserEmailFeedsForm() email_feeds_form.set_initial_values(user) tag_filter_form = forms.TagFilterSelectionForm(instance=user) action_status = None data = { 'active_tab': 'users', 'subscribed_tag_names': user.get_marked_tag_names('subscribed'), 'page_class': 'user-profile-page', 'tab_name': 'email_subscriptions', 'page_title': _('profile - email subscriptions'), 'email_feeds_form': email_feeds_form, 'tag_filter_selection_form': tag_filter_form, 'action_status': action_status, 'user_languages': user.languages.split() } context.update(data) #todo: really need only if subscribed tags are enabled context.update(view_context.get_for_tag_editor()) return render( request, 'user_profile/user_email_subscriptions.html', context )
def edit_question(request, id): """edit question view """ question = get_object_or_404(models.Post, id=id) if askbot_settings.READ_ONLY_MODE_ENABLED: return HttpResponseRedirect(question.get_absolute_url()) try: revision = question.revisions.get(revision=0) except models.PostRevision.DoesNotExist: revision = question.get_latest_revision() revision_form = None try: request.user.assert_can_edit_question(question) if request.method == 'POST': if request.POST['select_revision'] == 'true': #revert-type edit - user selected previous revision revision_form = forms.RevisionForm( question, revision, request.POST ) if revision_form.is_valid(): # Replace with those from the selected revision rev_id = revision_form.cleaned_data['revision'] revision = question.revisions.get(revision = rev_id) form = forms.EditQuestionForm( question=question, user=request.user, revision=revision ) else: form = forms.EditQuestionForm( request.POST, question=question, user=question.user, revision=revision ) else:#new content edit # Always check modifications against the latest revision form = forms.EditQuestionForm( request.POST, question=question, revision=revision, user=request.user, ) revision_form = forms.RevisionForm(question, revision) if form.is_valid(): if form.has_changed(): if form.can_edit_anonymously() and form.cleaned_data['reveal_identity']: question.thread.remove_author_anonymity() question.is_anonymous = False is_wiki = form.cleaned_data.get('wiki', question.wiki) post_privately = form.cleaned_data['post_privately'] suppress_email = form.cleaned_data['suppress_email'] user = form.get_post_user(request.user) user.edit_question( question=question, title=form.cleaned_data['title'], body_text=form.cleaned_data['text'], revision_comment=form.cleaned_data['summary'], tags=form.cleaned_data['tags'], wiki=is_wiki, edit_anonymously=form.cleaned_data['edit_anonymously'], is_private=post_privately, suppress_email=suppress_email, ip_addr=request.META.get('REMOTE_ADDR') ) if 'language' in form.cleaned_data: question.thread.set_language_code(form.cleaned_data['language']) return HttpResponseRedirect(question.get_absolute_url()) else: #request type was "GET" revision_form = forms.RevisionForm(question, revision) initial = { 'language': question.thread.language_code, 'post_privately': question.is_private(), 'wiki': question.wiki } form = forms.EditQuestionForm( question=question, revision=revision, user=request.user, initial=initial ) data = { 'page_class': 'edit-question-page', 'active_tab': 'questions', 'question': question, 'revision': revision, 'revision_form': revision_form, 'mandatory_tags': models.tag.get_mandatory_tags(), 'form' : form, 'tag_names': question.thread.get_tag_names(), 'category_tree_data': askbot_settings.CATEGORY_TREE } data.update(context.get_for_tag_editor()) return render(request, 'question_edit.html', data) except exceptions.PermissionDenied, e: request.user.message_set.create(message = unicode(e)) return HttpResponseRedirect(question.get_absolute_url())
try: group_id = int(request.GET.get('group_id', None)) form.initial['group_id'] = group_id except Exception: pass data = { 'active_tab': 'ask', 'page_class': 'ask-page', 'form' : form, 'mandatory_tags': models.tag.get_mandatory_tags(), 'email_validation_faq_url':reverse('faq') + '#validate', 'category_tree_data': askbot_settings.CATEGORY_TREE, 'tag_names': list()#need to keep context in sync with edit_question for tag editor } data.update(context.get_for_tag_editor()) return render(request, 'ask.html', data) @login_required @csrf.csrf_exempt def retag_question(request, id): """retag question view """ question = get_object_or_404(models.Post, id=id) try: request.user.assert_can_retag_question(question) if request.method == 'POST': form = forms.RetagQuestionForm(question, request.POST) if form.is_valid():
def ask(request):#view used to ask a new question """a view to ask a new question gives space for q title, body, tags and checkbox for to post as wiki user can start posting a question anonymously but then must login/register in order for the question go be shown """ if request.user.is_authenticated(): if request.user.is_read_only(): referer = request.META.get("HTTP_REFERER", reverse('questions')) request.user.message_set.create(message=_('Sorry, but you have only read access')) return HttpResponseRedirect(referer) if askbot_settings.READ_ONLY_MODE_ENABLED: return HttpResponseRedirect(reverse('index')) if request.method == 'POST': form = forms.AskForm(request.POST, user=request.user) if form.is_valid(): timestamp = timezone.now() title = form.cleaned_data['title'] wiki = form.cleaned_data['wiki'] tagnames = form.cleaned_data['tags'] text = form.cleaned_data['text'] ask_anonymously = form.cleaned_data['ask_anonymously'] post_privately = form.cleaned_data['post_privately'] group_id = form.cleaned_data.get('group_id', None) language = form.cleaned_data.get('language', None) content = u'{}\n\n{}\n\n{}'.format(title, tagnames, text) if akismet_check_spam(content, request): message = _('Spam was detected on your post, sorry if it was a mistake') raise exceptions.PermissionDenied(message) if request.user.is_authenticated(): drafts = models.DraftQuestion.objects.filter(author=request.user) drafts.delete() user = form.get_post_user(request.user) elif request.user.is_anonymous() and askbot_settings.ALLOW_ASK_UNREGISTERED: user = models.get_or_create_anonymous_user() ask_anonymously = True else: user = None if user: try: question = user.post_question( title=title, body_text=text, tags=tagnames, wiki=wiki, is_anonymous=ask_anonymously, is_private=post_privately, timestamp=timestamp, group_id=group_id, language=language, ip_addr=request.META.get('REMOTE_ADDR') ) signals.new_question_posted.send(None, question=question, user=user, form_data=form.cleaned_data ) return HttpResponseRedirect(question.get_absolute_url()) except exceptions.PermissionDenied as e: request.user.message_set.create(message = unicode(e)) return HttpResponseRedirect(reverse('index')) else: session_key=request.session.session_key if session_key is None: return HttpResponseForbidden() models.AnonymousQuestion.objects.create( session_key=session_key, title=title, tagnames=tagnames, wiki=wiki, is_anonymous=ask_anonymously, text=text, added_at=timestamp, ip_addr=request.META.get('REMOTE_ADDR'), ) return HttpResponseRedirect(url_utils.get_login_url()) if request.method == 'GET': form = forms.AskForm(user=request.user) #session key used only to enable anonymous asking #as django will autodelete empty sessions request.session['askbot_write_intent'] = True draft_title = '' draft_text = '' draft_tagnames = '' if request.user.is_authenticated(): drafts = models.DraftQuestion.objects.filter(author=request.user) if len(drafts) > 0: draft = drafts[0] draft_title = draft.title draft_text = draft.get_text() draft_tagnames = draft.tagnames form.initial = { 'ask_anonymously': request.REQUEST.get('ask_anonymously', False), 'tags': request.REQUEST.get('tags', draft_tagnames), 'text': request.REQUEST.get('text', draft_text), 'title': request.REQUEST.get('title', draft_title), 'post_privately': request.REQUEST.get('post_privately', False), 'language': get_language(), 'wiki': request.REQUEST.get('wiki', False), } if 'group_id' in request.REQUEST: try: group_id = int(request.GET.get('group_id', None)) form.initial['group_id'] = group_id except Exception: pass editor_is_folded = (askbot_settings.QUESTION_BODY_EDITOR_MODE=='folded' and \ askbot_settings.MIN_QUESTION_BODY_LENGTH==0 and \ form.initial['text'] == '') data = { 'active_tab': 'ask', 'page_class': 'ask-page', 'form' : form, 'editor_is_folded': editor_is_folded, 'mandatory_tags': models.tag.get_mandatory_tags(), 'email_validation_faq_url':reverse('faq') + '#validate', 'category_tree_data': askbot_settings.CATEGORY_TREE, 'tag_names': forms.split_tags(form.initial['tags']) } data.update(context.get_for_tag_editor()) return render(request, 'ask.html', data)
def edit_question(request, id): """edit question view """ question = get_object_or_404(models.Post, id=id) if askbot_settings.READ_ONLY_MODE_ENABLED: return HttpResponseRedirect(question.get_absolute_url()) revision = question.get_latest_revision() revision_form = None try: request.user.assert_can_edit_question(question) if request.method == "POST": if request.POST["select_revision"] == "true": # revert-type edit - user selected previous revision revision_form = forms.RevisionForm(question, revision, request.POST) if revision_form.is_valid(): # Replace with those from the selected revision rev_id = revision_form.cleaned_data["revision"] revision = question.revisions.get(revision=rev_id) form = forms.EditQuestionForm(question=question, user=request.user, revision=revision) else: form = forms.EditQuestionForm( request.POST, question=question, user=question.user, revision=revision ) else: # new content edit # Always check modifications against the latest revision form = forms.EditQuestionForm(request.POST, question=question, revision=revision, user=request.user) revision_form = forms.RevisionForm(question, revision) if form.is_valid(): if form.has_changed(): if form.cleaned_data["reveal_identity"]: question.thread.remove_author_anonymity() is_anon_edit = form.cleaned_data["stay_anonymous"] is_wiki = form.cleaned_data.get("wiki", question.wiki) post_privately = form.cleaned_data["post_privately"] suppress_email = form.cleaned_data["suppress_email"] user = form.get_post_user(request.user) user.edit_question( question=question, title=form.cleaned_data["title"], body_text=form.cleaned_data["text"], revision_comment=form.cleaned_data["summary"], tags=form.cleaned_data["tags"], wiki=is_wiki, edit_anonymously=is_anon_edit, is_private=post_privately, suppress_email=suppress_email, ip_addr=request.META.get("REMOTE_ADDR"), ) if "language" in form.cleaned_data: question.thread.set_language_code(form.cleaned_data["language"]) return HttpResponseRedirect(question.get_absolute_url()) else: # request type was "GET" revision_form = forms.RevisionForm(question, revision) initial = { "language": question.thread.language_code, "post_privately": question.is_private(), "wiki": question.wiki, } form = forms.EditQuestionForm(question=question, revision=revision, user=request.user, initial=initial) data = { "page_class": "edit-question-page", "active_tab": "questions", "question": question, "revision": revision, "revision_form": revision_form, "mandatory_tags": models.tag.get_mandatory_tags(), "form": form, "tag_names": question.thread.get_tag_names(), "category_tree_data": askbot_settings.CATEGORY_TREE, } data.update(context.get_for_tag_editor()) return render(request, "question_edit.html", data) except exceptions.PermissionDenied, e: request.user.message_set.create(message=unicode(e)) return HttpResponseRedirect(question.get_absolute_url())
def edit_question(request, id): """edit question view """ question = get_object_or_404(models.Post, id=id) revision = question.get_latest_revision() revision_form = None try: request.user.assert_can_edit_question(question) if request.method == 'POST': if request.POST['select_revision'] == 'true': #revert-type edit - user selected previous revision revision_form = forms.RevisionForm(question, revision, request.POST) if revision_form.is_valid(): # Replace with those from the selected revision rev_id = revision_form.cleaned_data['revision'] revision = question.revisions.get(revision=rev_id) form = forms.EditQuestionForm(question=question, user=request.user, revision=revision) else: form = forms.EditQuestionForm(request.POST, question=question, user=question.user, revision=revision) else: #new content edit # Always check modifications against the latest revision form = forms.EditQuestionForm( request.POST, question=question, revision=revision, user=request.user, ) revision_form = forms.RevisionForm(question, revision) if form.is_valid(): if form.has_changed(): if form.cleaned_data['reveal_identity']: question.thread.remove_author_anonymity() if 'language' in form.cleaned_data: question.thread.language_code = form.cleaned_data[ 'language'] is_anon_edit = form.cleaned_data['stay_anonymous'] is_wiki = form.cleaned_data.get('wiki', question.wiki) post_privately = form.cleaned_data['post_privately'] suppress_email = form.cleaned_data['suppress_email'] user = form.get_post_user(request.user) user.edit_question( question=question, title=form.cleaned_data['title'], body_text=form.cleaned_data['text'], revision_comment=form.cleaned_data['summary'], tags=form.cleaned_data['tags'], wiki=is_wiki, edit_anonymously=is_anon_edit, is_private=post_privately, suppress_email=suppress_email) return HttpResponseRedirect(question.get_absolute_url()) else: #request type was "GET" revision_form = forms.RevisionForm(question, revision) initial = { 'language': question.thread.language_code, 'post_privately': question.is_private(), 'wiki': question.wiki } form = forms.EditQuestionForm(question=question, revision=revision, user=request.user, initial=initial) data = { 'page_class': 'edit-question-page', 'active_tab': 'questions', 'question': question, 'revision': revision, 'revision_form': revision_form, 'mandatory_tags': models.tag.get_mandatory_tags(), 'form': form, 'tag_names': question.thread.get_tag_names(), 'category_tree_data': askbot_settings.CATEGORY_TREE } data.update(context.get_for_tag_editor()) return render(request, 'question_edit.html', data) except exceptions.PermissionDenied, e: request.user.message_set.create(message=unicode(e)) return HttpResponseRedirect(question.get_absolute_url())
def edit_question(request, id): """edit question view """ question = get_object_or_404(models.Post, id=id) if askbot_settings.READ_ONLY_MODE_ENABLED: return redirect(question) try: revision = question.revisions.get(revision=0) except models.PostRevision.DoesNotExist: revision = question.get_latest_revision() revision_form = None try: request.user.assert_can_edit_question(question) if request.method == 'POST': if request.POST['select_revision'] == 'true': # revert-type edit - user selected previous revision revision_form = forms.RevisionForm(question, revision, request.POST) if revision_form.is_valid(): # Replace with those from the selected revision rev_id = revision_form.cleaned_data['revision'] revision = question.revisions.get(revision=rev_id) form = forms.EditQuestionForm(question=question, user=request.user, revision=revision) else: form = forms.EditQuestionForm(request.POST, question=question, user=question.user, revision=revision) else: # new content edit # Always check modifications against the latest revision form = forms.EditQuestionForm(request.POST, question=question, revision=revision, user=request.user) revision_form = forms.RevisionForm(question, revision) if form.is_valid(): if form.has_changed(): if form.can_edit_anonymously( ) and form.cleaned_data['reveal_identity']: question.thread.remove_author_anonymity() question.is_anonymous = False is_wiki = form.cleaned_data.get('wiki', question.wiki) post_privately = form.cleaned_data['post_privately'] suppress_email = form.cleaned_data['suppress_email'] user = form.get_post_user(request.user) user.edit_question( question=question, title=form.cleaned_data['title'], body_text=form.cleaned_data['text'], revision_comment=form.cleaned_data['summary'], tags=form.cleaned_data['tags'], wiki=is_wiki, edit_anonymously=form. cleaned_data['edit_anonymously'], is_private=post_privately, suppress_email=suppress_email, ip_addr=request.META.get('REMOTE_ADDR')) if 'language' in form.cleaned_data: question.thread.set_language_code( form.cleaned_data['language']) return redirect(question) else: # request type was "GET" revision_form = forms.RevisionForm(question, revision) initial = { 'language': question.thread.language_code, 'post_privately': question.is_private(), 'wiki': question.wiki } form = forms.EditQuestionForm(question=question, revision=revision, user=request.user, initial=initial) data = { 'page_class': 'edit-question-page', 'active_tab': 'questions', 'question': question, 'revision': revision, 'revision_form': revision_form, 'mandatory_tags': models.tag.get_mandatory_tags(), 'form': form, 'tag_names': question.thread.get_tag_names(), 'category_tree_data': askbot_settings.CATEGORY_TREE } data.update(context.get_for_tag_editor()) return render(request, 'question_edit.jinja', data) except 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)
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 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 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 edit_exercise(request, id): """edit exercise view """ exercise = get_object_or_404(models.Post, id=id) revision = exercise.get_latest_revision() revision_form = None try: request.user.assert_can_edit_exercise(exercise) if request.method == 'POST': if request.POST['select_revision'] == 'true': #revert-type edit - user selected previous revision revision_form = forms.RevisionForm( exercise, revision, request.POST ) if revision_form.is_valid(): # Replace with those from the selected revision rev_id = revision_form.cleaned_data['revision'] revision = exercise.revisions.get(revision = rev_id) form = forms.EditExerciseForm( exercise = exercise, user = request.user, revision = revision ) else: form = forms.EditExerciseForm( request.POST, exercise = exercise, user = request.user, revision = revision ) else:#new content edit # Always check modifications against the latest revision form = forms.EditExerciseForm( request.POST, exercise = exercise, revision = revision, user = request.user, ) revision_form = forms.RevisionForm(exercise, revision) if form.is_valid(): if form.has_changed(): if form.cleaned_data['reveal_identity']: exercise.thread.remove_author_anonymity() is_anon_edit = form.cleaned_data['stay_anonymous'] is_wiki = form.cleaned_data.get('wiki', exercise.wiki) post_privately = form.cleaned_data['post_privately'] user = form.get_post_user(request.user) user.edit_exercise( exercise = exercise, title = form.cleaned_data['title'], body_text = form.cleaned_data['text'], revision_comment = form.cleaned_data['summary'], tags = form.cleaned_data['tags'], wiki = is_wiki, edit_anonymously = is_anon_edit, is_private = post_privately ) return HttpResponseRedirect(exercise.get_absolute_url()) else: #request type was "GET" revision_form = forms.RevisionForm(exercise, revision) initial = { 'post_privately': exercise.is_private(), 'wiki': exercise.wiki } form = forms.EditExerciseForm( exercise = exercise, revision = revision, user = request.user, initial = initial ) data = { 'page_class': 'edit-exercise-page', 'active_tab': 'exercises', 'exercise': exercise, 'revision': revision, 'revision_form': revision_form, 'mandatory_tags': models.tag.get_mandatory_tags(), 'form' : form, 'tag_names': exercise.thread.get_tag_names(), 'category_tree_data': askbot_settings.CATEGORY_TREE } data.update(context.get_for_tag_editor()) return render_into_skin('exercise_edit.html', data, request) except exceptions.PermissionDenied, e: request.user.message_set.create(message = unicode(e)) return HttpResponseRedirect(exercise.get_absolute_url())
def ask(request): #view used to ask a new question """a view to ask a new question gives space for q title, body, tags and checkbox for to post as wiki user can start posting a question anonymously but then must login/register in order for the question go be shown """ if request.user.is_authenticated(): if request.user.is_read_only(): referer = request.META.get("HTTP_REFERER", reverse('questions')) request.user.message_set.create( message=_('Sorry, but you have only read access')) return HttpResponseRedirect(referer) if askbot_settings.READ_ONLY_MODE_ENABLED: return HttpResponseRedirect(reverse('index')) if request.method == 'POST': form = forms.AskForm(request.POST, user=request.user) if form.is_valid(): timestamp = timezone.now() title = form.cleaned_data['title'] wiki = form.cleaned_data['wiki'] tagnames = form.cleaned_data['tags'] text = form.cleaned_data['text'] ask_anonymously = form.cleaned_data['ask_anonymously'] post_privately = form.cleaned_data['post_privately'] group_id = form.cleaned_data.get('group_id', None) language = form.cleaned_data.get('language', None) content = '{}\n\n{}\n\n{}'.format(title, tagnames, text) if akismet_check_spam(content, request): message = _( 'Spam was detected on your post, sorry if it was a mistake' ) raise exceptions.PermissionDenied(message) if request.user.is_authenticated(): drafts = models.DraftQuestion.objects.filter( author=request.user) drafts.delete() user = form.get_post_user(request.user) elif request.user.is_anonymous( ) and askbot_settings.ALLOW_ASK_UNREGISTERED: user = models.get_or_create_anonymous_user() ask_anonymously = True else: user = None if user: try: question = user.post_question( title=title, body_text=text, tags=tagnames, wiki=wiki, is_anonymous=ask_anonymously, is_private=post_privately, timestamp=timestamp, group_id=group_id, language=language, ip_addr=request.META.get('REMOTE_ADDR')) signals.new_question_posted.send( None, question=question, user=user, form_data=form.cleaned_data) return HttpResponseRedirect(question.get_absolute_url()) except exceptions.PermissionDenied as e: request.user.message_set.create(message=unicode(e)) return HttpResponseRedirect(reverse('index')) else: session_key = request.session.session_key if session_key is None: return HttpResponseForbidden() models.AnonymousQuestion.objects.create( session_key=session_key, title=title, tagnames=tagnames, wiki=wiki, is_anonymous=ask_anonymously, text=text, added_at=timestamp, ip_addr=request.META.get('REMOTE_ADDR'), ) return HttpResponseRedirect(url_utils.get_login_url()) if request.method == 'GET': form = forms.AskForm(user=request.user) #session key used only to enable anonymous asking #as django will autodelete empty sessions request.session['askbot_write_intent'] = True draft_title = '' draft_text = '' draft_tagnames = '' if request.user.is_authenticated(): drafts = models.DraftQuestion.objects.filter(author=request.user) if len(drafts) > 0: draft = drafts[0] draft_title = draft.title draft_text = draft.get_text() draft_tagnames = draft.tagnames form.initial = { 'ask_anonymously': request.REQUEST.get('ask_anonymously', False), 'tags': request.REQUEST.get('tags', draft_tagnames), 'text': request.REQUEST.get('text', draft_text), 'title': request.REQUEST.get('title', draft_title), 'post_privately': request.REQUEST.get('post_privately', False), 'language': get_language(), 'wiki': request.REQUEST.get('wiki', False), } if 'group_id' in request.REQUEST: try: group_id = int(request.GET.get('group_id', None)) form.initial['group_id'] = group_id except Exception: pass editor_is_folded = (askbot_settings.QUESTION_BODY_EDITOR_MODE=='folded' and \ askbot_settings.MIN_QUESTION_BODY_LENGTH==0 and \ form.initial['text'] == '') data = { 'active_tab': 'ask', 'page_class': 'ask-page', 'form': form, 'editor_is_folded': editor_is_folded, 'mandatory_tags': models.tag.get_mandatory_tags(), 'email_validation_faq_url': reverse('faq') + '#validate', 'category_tree_data': askbot_settings.CATEGORY_TREE, 'tag_names': forms.split_tags(form.initial['tags']) } data.update(context.get_for_tag_editor()) return render(request, 'ask.html', data)
def ask(request): # view used to ask a new question """a view to ask a new question gives space for q title, body, tags and checkbox for to post as wiki user can start posting a question anonymously but then must login/register in order for the question go be shown """ if request.user.is_authenticated(): if request.user.is_read_only(): referer = request.META.get("HTTP_REFERER", reverse('questions')) # request.user.message_set.create(message=_('Sorry, but you have only read access')) django_messages.info(request, _('Sorry, but you have only read access')) return redirect(referer) if askbot_settings.READ_ONLY_MODE_ENABLED: return redirect('index') if request.method == 'POST': form = forms.AskForm(request.POST, user=request.user) if form.is_valid(): timestamp = timezone.now() title = form.cleaned_data['title'] wiki = form.cleaned_data['wiki'] tagnames = form.cleaned_data['tags'] text = form.cleaned_data['text'] ask_anonymously = form.cleaned_data['ask_anonymously'] post_privately = form.cleaned_data['post_privately'] group_id = form.cleaned_data.get('group_id', None) language = form.cleaned_data.get('language', None) if request.user.is_authenticated(): drafts = models.DraftQuestion.objects.filter(author=request.user) drafts.delete() user = form.get_post_user(request.user) elif request.user.is_anonymous() and askbot_settings.ALLOW_ASK_UNREGISTERED: user = models.get_or_create_anonymous_user() ask_anonymously = True else: user = None if user: try: question = user.post_question( title=title, body_text=text, tags=tagnames, wiki=wiki, is_anonymous=ask_anonymously, is_private=post_privately, timestamp=timestamp, group_id=group_id, language=language, ip_addr=request.META.get('REMOTE_ADDR') ) signals.new_question_posted.send( None, question=question, user=user, form_data=form.cleaned_data) return redirect(question) except 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('index') else: request.session.flush() session_key = request.session.session_key models.AnonymousQuestion.objects.create( session_key=session_key, title=title, tagnames=tagnames, wiki=wiki, is_anonymous=ask_anonymously, text=text, added_at=timestamp, ip_addr=request.META.get('REMOTE_ADDR'), ) return redirect(url_utils.get_login_url()) if request.method == 'GET': form = forms.AskForm(user=request.user) draft_title = '' draft_text = '' draft_tagnames = '' if request.user.is_authenticated(): drafts = models.DraftQuestion.objects.filter(author=request.user) if len(drafts) > 0: draft = drafts[0] draft_title = draft.title draft_text = draft.text draft_tagnames = draft.tagnames form.initial = { 'ask_anonymously': request.REQUEST.get('ask_anonymously', False), 'tags': request.REQUEST.get('tags', draft_tagnames), 'text': request.REQUEST.get('text', draft_text), 'title': request.REQUEST.get('title', draft_title), 'post_privately': request.REQUEST.get('post_privately', False), 'language': get_language(), 'wiki': request.REQUEST.get('wiki', False), } if 'group_id' in request.REQUEST: try: group_id = int(request.GET.get('group_id', None)) form.initial['group_id'] = group_id except Exception: pass editor_is_folded = \ askbot_settings.QUESTION_BODY_EDITOR_MODE == 'folded' and \ askbot_settings.MIN_QUESTION_BODY_LENGTH == 0 and \ form.initial['text'] == '' data = { 'active_tab': 'ask', 'page_class': 'ask-page', 'form': form, 'editor_is_folded': editor_is_folded, 'mandatory_tags': models.tag.get_mandatory_tags(), 'email_validation_faq_url': reverse('faq') + '# validate', 'category_tree_data': askbot_settings.CATEGORY_TREE, 'tag_names': list(), # need to keep context in sync with edit_question for tag editor } data.update(context.get_for_tag_editor()) return render(request, 'ask.jinja', 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)
group_id = int(request.GET.get('group_id', None)) form.initial['group_id'] = group_id except Exception: pass data = { 'active_tab': 'ask', 'page_class': 'ask-page', 'form': form, 'mandatory_tags': models.tag.get_mandatory_tags(), 'email_validation_faq_url': reverse('faq') + '#validate', 'category_tree_data': askbot_settings.CATEGORY_TREE, 'tag_names': list() #need to keep context in sync with edit_question for tag editor } data.update(context.get_for_tag_editor()) return render(request, 'ask.html', data) @login_required @csrf.csrf_exempt def retag_question(request, id): """retag question view """ question = get_object_or_404(models.Post, id=id) try: request.user.assert_can_retag_question(question) if request.method == 'POST': form = forms.RetagQuestionForm(question, request.POST)
def questions(request, **kwargs): """ List of Questions, Tagged questions, and Unanswered questions. matching search query or user selection """ #before = timezone.now() if request.method != 'GET': return HttpResponseNotAllowed(['GET']) #①request.user.is_authenticated()=False search_state = SearchState( user_logged_in=request.user.is_authenticated(), **kwargs ) #①request.user=AnonymousUser: AnonymousUser, #①search_state=scope:all/sort:activity-desc/page:1/ qs, meta_data = models.Thread.objects.run_advanced_search( request_user=request.user, search_state=search_state ) #meta_data={'non_existing_tags': []} if meta_data['non_existing_tags']: search_state = search_state.remove_tags(meta_data['non_existing_tags']) #①qs=[],search_state.page_size=30 paginator = Paginator(qs, search_state.page_size) if paginator.num_pages < search_state.page: search_state.page = 1 page = paginator.page(search_state.page) page.object_list = list(page.object_list) # evaluate the queryset # INFO: Because for the time being we need question posts and thread authors # down the pipeline, we have to precache them in thread objects #①page.object_list=[] models.Thread.objects.precache_view_data_hack(threads=page.object_list) related_tags = Tag.objects.get_related_to_search( threads=page.object_list, ignored_tag_names=meta_data.get('ignored_tag_names',[]) ) tag_list_type = askbot_settings.TAG_LIST_FORMAT #①tag_list_type=u'list' if tag_list_type == 'cloud': #force cloud to sort by name related_tags = sorted(related_tags, key = operator.attrgetter('name')) contributors = list( models.Thread.objects.get_thread_contributors( thread_list=page.object_list ).only( 'id', 'username', 'askbot_profile__gravatar' ) ) paginator_context = { 'is_paginated' : (paginator.count > search_state.page_size), 'pages': paginator.num_pages, 'current_page_number': search_state.page, 'page_object': page, 'base_url' : search_state.query_string(), 'page_size' : search_state.page_size, } #get url for the rss feed context_feed_url = reverse('latest_questions_feed') #①context_feed_url=u'/feeds/rss/' # We need to pass the rss feed url based # on the search state to the template. # We use QueryDict to get a querystring # from dicts and arrays. Much cleaner # than parsing and string formating. rss_query_dict = QueryDict("").copy() #①search_state.query=None if search_state.query: # We have search string in session - pass it to # the QueryDict rss_query_dict.update({"q": search_state.query}) #①search_state.tags=None if search_state.tags: # We have tags in session - pass it to the # QueryDict but as a list - we want tags+ rss_query_dict.setlist('tags', search_state.tags) context_feed_url += '?' + rss_query_dict.urlencode() reset_method_count = len(filter(None, [search_state.query, search_state.tags, meta_data.get('author_name', None)])) if request.is_ajax(): q_count = paginator.count #todo: words question_counter = ungettext('%(q_num)s question', '%(q_num)s questions', q_count) question_counter = question_counter % {'q_num': humanize.intcomma(q_count),} if q_count > search_state.page_size: paginator_tpl = get_template('main_page/paginator.html') paginator_html = paginator_tpl.render( RequestContext( request, { 'context': paginator_context, 'questions_count': q_count, 'page_size' : search_state.page_size, 'search_state': search_state, } ) ) else: paginator_html = '' questions_tpl = get_template('main_page/questions_loop.html') questions_html = questions_tpl.render( RequestContext( request, { 'threads': page, 'search_state': search_state, 'reset_method_count': reset_method_count, 'request': request } ) ) ajax_data = { 'query_data': { 'tags': search_state.tags, 'sort_order': search_state.sort, 'ask_query_string': search_state.ask_query_string(), }, 'paginator': paginator_html, 'question_counter': question_counter, 'faces': [],#[extra_tags.gravatar(contributor, 48) for contributor in contributors], 'feed_url': context_feed_url, 'query_string': search_state.query_string(), 'page_size' : search_state.page_size, 'questions': questions_html.replace('\n',''), 'non_existing_tags': meta_data['non_existing_tags'], } related_tags_tpl = get_template('widgets/related_tags.html') related_tags_data = { 'tags': related_tags, 'tag_list_type': tag_list_type, 'query_string': search_state.query_string(), 'search_state': search_state, 'language_code': translation.get_language(), } if tag_list_type == 'cloud': related_tags_data['font_size'] = extra_tags.get_tag_font_size(related_tags) ajax_data['related_tags_html'] = related_tags_tpl.render( RequestContext(request, related_tags_data) ) #here we add and then delete some items #to allow extra context processor to work ajax_data['tags'] = related_tags ajax_data['interesting_tag_names'] = None ajax_data['threads'] = page extra_context = context.get_extra( 'ASKBOT_QUESTIONS_PAGE_EXTRA_CONTEXT', request, ajax_data ) del ajax_data['tags'] del ajax_data['interesting_tag_names'] del ajax_data['threads'] ajax_data.update(extra_context) return HttpResponse(simplejson.dumps(ajax_data), content_type='application/json') else: # non-AJAX branch template_data = { 'active_tab': 'questions', 'author_name' : meta_data.get('author_name',None), 'contributors' : contributors, 'context' : paginator_context, 'is_unanswered' : False,#remove this from template 'interesting_tag_names': meta_data.get('interesting_tag_names', None), 'ignored_tag_names': meta_data.get('ignored_tag_names', None), 'subscribed_tag_names': meta_data.get('subscribed_tag_names', None), 'language_code': translation.get_language(), 'name_of_anonymous_user' : models.get_name_of_anonymous_user(), 'page_class': 'main-page', 'page_size': search_state.page_size, 'query': search_state.query, 'threads' : page, 'questions_count' : paginator.count, 'reset_method_count': reset_method_count, 'scope': search_state.scope, 'show_sort_by_relevance': conf.should_show_sort_by_relevance(), 'search_tags' : search_state.tags, 'sort': search_state.sort, 'tab_id' : search_state.sort, 'tags' : related_tags, 'tag_list_type' : tag_list_type, 'font_size' : extra_tags.get_tag_font_size(related_tags), 'display_tag_filter_strategy_choices': conf.get_tag_display_filter_strategy_choices(), 'email_tag_filter_strategy_choices': conf.get_tag_email_filter_strategy_choices(), 'query_string': search_state.query_string(), 'search_state': search_state, 'feed_url': context_feed_url } extra_context = context.get_extra( 'ASKBOT_QUESTIONS_PAGE_EXTRA_CONTEXT', request, template_data ) template_data.update(extra_context) template_data.update(context.get_for_tag_editor()) #and one more thing:) give admin user heads up about #setting the domain name if they have not done that yet #todo: move this out to a separate middleware if request.user.is_authenticated() and request.user.is_administrator(): if domain_is_bad(): url = askbot_settings.get_setting_url(('QA_SITE_SETTINGS', 'APP_URL')) msg = _( 'Please go to Settings -> %s ' 'and set the base url for your site to function properly' ) % url request.user.message_set.create(message=msg) #①template_data={'contributors': [], 'ignored_tag_names': None, 'author_name': None, 'language_code': 'en', 'active_tab': 'questions', 'query': None, 'tag_list_type': u'list', 'display_tag_filter_strategy_choices': ((0, <django.utils.functional.__proxy__ object at 0x00000000059CDF28>), (1, <django.utils.functional.__proxy__ object at 0x00000000059CDF98>), (2, <django.utils.functional.__proxy__ object at 0x00000000059D5048>)), 'is_unanswered': False, 'feed_url': u'/feeds/rss/', 'questions_count': 0, 'tags': [], 'page_size': 30, 'search_state': <askbot.search.state_manager.SearchState object at 0x0000000006D9ECC0>, 'tab_id': 'activity-desc', 'sort': 'activity-desc', 'context': {'page_object': <Page 1 of 1>, 'base_url': u'scope:all/sort:activity-desc/page:1/', 'page_size': 30, 'current_page_number': 1, 'is_paginated': False, 'pages': 1}, 'search_tags': [], 'reset_method_count': 0, 'subscribed_tag_names': None, 'threads': <Page 1 of 1>, 'scope': u'all', 'font_size': {}, 'email_tag_filter_strategy_choices': ((0, <django.utils.functional.__proxy__ object at 0x00000000059D5128>), (1, <django.utils.functional.__proxy__ object at 0x00000000059D5198>), (2, <django.utils.functional.__proxy__ object at 0x00000000059D5208>)), 'show_sort_by_relevance': False, 'tag_editor_settings': '{"tag_forbidden_first_chars": "#", "max_tag_length": 20, "force_lowercase_tags": false, "max_tags_per_post": 5, "messages": {"wrong_first_char": "# is not a valid character at the beginning of tags, use only letters and numbers", "wrong_chars": "please use letters, numbers and characters \\"-+.#\\"", "required": "tags are required"}, "tags_are_required": false}', 'page_class': 'main-page', 'query_string': u'scope:all/sort:activity-desc/page:1/', 'name_of_anonymous_user': u'Anonymous', 'interesting_tag_names': None} return render(request, 'main_page.html', template_data)
def ask(request): # view used to ask a new question """a view to ask a new question gives space for q title, body, tags and checkbox for to post as wiki user can start posting a question anonymously but then must login/register in order for the question go be shown """ if request.user.is_authenticated(): if request.user.is_read_only(): referer = request.META.get("HTTP_REFERER", reverse('questions')) # request.user.message_set.create(message=_('Sorry, but you have only read access')) django_messages.info(request, _('Sorry, but you have only read access')) return redirect(referer) if askbot_settings.READ_ONLY_MODE_ENABLED: return redirect('index') if request.method == 'POST': form = forms.AskForm(request.POST, user=request.user) if form.is_valid(): timestamp = timezone.now() title = form.cleaned_data['title'] wiki = form.cleaned_data['wiki'] tagnames = form.cleaned_data['tags'] text = form.cleaned_data['text'] ask_anonymously = form.cleaned_data['ask_anonymously'] post_privately = form.cleaned_data['post_privately'] group_id = form.cleaned_data.get('group_id', None) language = form.cleaned_data.get('language', None) if request.user.is_authenticated(): drafts = models.DraftQuestion.objects.filter( author=request.user) drafts.delete() user = form.get_post_user(request.user) elif request.user.is_anonymous( ) and askbot_settings.ALLOW_ASK_UNREGISTERED: user = models.get_or_create_anonymous_user() ask_anonymously = True else: user = None if user: try: question = user.post_question( title=title, body_text=text, tags=tagnames, wiki=wiki, is_anonymous=ask_anonymously, is_private=post_privately, timestamp=timestamp, group_id=group_id, language=language, ip_addr=request.META.get('REMOTE_ADDR')) signals.new_question_posted.send( None, question=question, user=user, form_data=form.cleaned_data) return redirect(question) except 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('index') else: request.session.flush() session_key = request.session.session_key models.AnonymousQuestion.objects.create( session_key=session_key, title=title, tagnames=tagnames, wiki=wiki, is_anonymous=ask_anonymously, text=text, added_at=timestamp, ip_addr=request.META.get('REMOTE_ADDR'), ) return redirect(url_utils.get_login_url()) if request.method == 'GET': form = forms.AskForm(user=request.user) draft_title = '' draft_text = '' draft_tagnames = '' if request.user.is_authenticated(): drafts = models.DraftQuestion.objects.filter(author=request.user) if len(drafts) > 0: draft = drafts[0] draft_title = draft.title draft_text = draft.text draft_tagnames = draft.tagnames form.initial = { 'ask_anonymously': request.REQUEST.get('ask_anonymously', False), 'tags': request.REQUEST.get('tags', draft_tagnames), 'text': request.REQUEST.get('text', draft_text), 'title': request.REQUEST.get('title', draft_title), 'post_privately': request.REQUEST.get('post_privately', False), 'language': get_language(), 'wiki': request.REQUEST.get('wiki', False), } if 'group_id' in request.REQUEST: try: group_id = int(request.GET.get('group_id', None)) form.initial['group_id'] = group_id except Exception: pass editor_is_folded = \ askbot_settings.QUESTION_BODY_EDITOR_MODE == 'folded' and \ askbot_settings.MIN_QUESTION_BODY_LENGTH == 0 and \ form.initial['text'] == '' data = { 'active_tab': 'ask', 'page_class': 'ask-page', 'form': form, 'editor_is_folded': editor_is_folded, 'mandatory_tags': models.tag.get_mandatory_tags(), 'email_validation_faq_url': reverse('faq') + '# validate', 'category_tree_data': askbot_settings.CATEGORY_TREE, 'tag_names': list( ), # need to keep context in sync with edit_question for tag editor } data.update(context.get_for_tag_editor()) return render(request, 'ask.jinja', data)