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)
try: show_post.assert_is_visible_to(request.user) except django_exceptions.PermissionDenied, 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!
try: show_post.assert_is_visible_to(request.user) except django_exceptions.PermissionDenied, error: request.user.message_set.create(message = unicode(error)) return HttpResponseRedirect(reverse('question', kwargs = {'id': id})) thread = question_post.thread if getattr(django_settings, 'ASKBOT_MULTILINGUAL', False): 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!