From 1a4e435460bf3ea25a2b03e50eeb5ac67838502c Mon Sep 17 00:00:00 2001 From: Tomasz Zielinski Date: Tue, 27 Dec 2011 14:49:42 +0100 Subject: questions() view cleanup and conversion to Post --- askbot/models/question.py | 53 +++---- askbot/skins/default/templates/macros.html | 2 +- askbot/skins/default/templates/main_page.html | 6 +- .../templates/main_page/questions_loop.html | 6 +- askbot/skins/default/templates/question.html | 2 +- .../templates/user_profile/users_questions.html | 2 +- .../templates/widgets/question_summary.html | 28 ++-- askbot/views/readers.py | 157 +++++++-------------- 8 files changed, 90 insertions(+), 166 deletions(-) diff --git a/askbot/models/question.py b/askbot/models/question.py index b9d18c7f..d0a30fcc 100644 --- a/askbot/models/question.py +++ b/askbot/models/question.py @@ -133,7 +133,7 @@ class ThreadManager(models.Manager): # #fallback to dumb title match search # return self.filter(title__icontains=search_query) - def run_advanced_search(self, request_user=None, search_state=None): + def run_advanced_search(self, request_user=None, search_state=None): # TODO: !! review and fix this """ all parameters are guaranteed to be clean however may not relate to database - in that case @@ -235,7 +235,7 @@ class ThreadManager(models.Manager): qs_thread = qs.distinct() ### - qs = Question.objects.filter(thread__in=qs_thread) # HACH: GO BACK To QUESTIONS + qs = Post.objects.filter(post_type='question', thread__in=qs_thread) # HACH: GO BACK To QUESTIONS, otherwise we cannot sort properly! qs = qs.select_related('thread__last_activity_by') if sort_method != 'relevance-desc': @@ -264,6 +264,21 @@ class ThreadManager(models.Manager): return qs, meta_data, related_tags + #todo: this function is similar to get_response_receivers - profile this function against the other one + def get_thread_contributors(self, thread_list): + """Returns query set of Thread contributors""" + u_id = Post.objects.filter(post_type__in=['question', 'answer'], thread__in=thread_list).values_list('author', flat=True) + + #todo: this does not belong gere - here we select users with real faces + #first and limit the number of users in the result for display + #on the main page, we might also want to completely hide fake gravatars + #and show only real images and the visitors - even if he does not have + #a real image and try to prompt him/her to upload a picture + from askbot.conf import settings as askbot_settings + avatar_limit = askbot_settings.SIDEBAR_MAIN_AVATAR_LIMIT + contributors = User.objects.filter(id__in=u_id).order_by('avatar_type', '?')[:avatar_limit] + return contributors + class Thread(models.Model): title = models.CharField(max_length=300) @@ -846,40 +861,6 @@ class QuestionQuerySet(models.query.QuerySet): question_list.append(question) return question_list - #todo: this function is similar to get_response_receivers - #profile this function against the other one - #todo: maybe this must be a query set method, not manager method - def get_question_and_answer_contributors(self, question_list): - """returns query set of Thread contributors - """ - #todo: goes to thread - queries will be simplified too - answer_list = [] - #question_list = list(question_list)#important for MySQL, b/c it does not support - from askbot.models.answer import Answer - q_id = [question.id for question in question_list] - a_id = list(Answer.objects.filter(question__in=q_id).values_list('id', flat=True)) - u_id = set(self.filter(id__in=q_id).values_list('author', flat=True)) - u_id = u_id.union( - set(Answer.objects.filter(id__in=a_id).values_list('author', flat=True)) - ) - - #todo: this does not belong gere - here we select users with real faces - #first and limit the number of users in the result for display - #on the main page, we might also want to completely hide fake gravatars - #and show only real images and the visitors - even if he does not have - #a real image and try to prompt him/her to upload a picture - from askbot.conf import settings as askbot_settings - avatar_limit = askbot_settings.SIDEBAR_MAIN_AVATAR_LIMIT - contributors = User.objects.filter(id__in=u_id).order_by('avatar_type', '?')[:avatar_limit] - #print contributors - #could not optimize this query with indices so it was split into what's now above - #contributors = User.objects.filter( - # models.Q(questions__in=question_list) \ - # | models.Q(answers__in=answer_list) - # ).distinct() - #contributors = list(contributors) - return contributors - def get_author_list(self, **kwargs): #todo: - this is duplication - answer manager also has this method #will be gone when models are consolidated diff --git a/askbot/skins/default/templates/macros.html b/askbot/skins/default/templates/macros.html index 29b2fe0f..b5591b47 100644 --- a/askbot/skins/default/templates/macros.html +++ b/askbot/skins/default/templates/macros.html @@ -229,7 +229,7 @@ poor design of the data or methods on data objects #} {% endfor %} {%- endmacro -%} -{%- macro question_summary(question, extra_class=None, query_string=None) -%} +{%- macro question_summary(thread, question, extra_class=None, query_string=None) -%} {%include "widgets/question_summary.html" %} {%- endmacro -%} diff --git a/askbot/skins/default/templates/main_page.html b/askbot/skins/default/templates/main_page.html index d0cddc68..a0635a7a 100644 --- a/askbot/skins/default/templates/main_page.html +++ b/askbot/skins/default/templates/main_page.html @@ -12,7 +12,11 @@ {% block content %} {% include "main_page/tab_bar.html" %} {% include "main_page/headline.html" %} - {% include "main_page/content.html" %} + {# ==== BEGIN: main_page/content.html === #} +
+ {% include "main_page/questions_loop.html" %} +
+ {# ==== END: main_page/content.html === #} {% include "main_page/paginator.html" %} {% endblock %} {% block sidebar %} diff --git a/askbot/skins/default/templates/main_page/questions_loop.html b/askbot/skins/default/templates/main_page/questions_loop.html index 8e6c0492..f9d62f9c 100644 --- a/askbot/skins/default/templates/main_page/questions_loop.html +++ b/askbot/skins/default/templates/main_page/questions_loop.html @@ -1,11 +1,11 @@ {% import "macros.html" as macros %} {% cache 0 "questions" questions search_tags scope sort query context.page context.page_size language_code %} - {% for question in questions.object_list %} - {{macros.question_summary(question, query_string=query_string)}} + {% for question_post in questions.object_list %} + {{macros.question_summary(question_post.thread, question_post, query_string=query_string)}} {% endfor %} {% endcache %} {# comment todo: fix css here #} -{% if questions_count == 0 %} +{% if threadss_count == 0 %} {% include "main_page/nothing_found.html" %} {% else %}
diff --git a/askbot/skins/default/templates/question.html b/askbot/skins/default/templates/question.html index 6fff53b0..5e2c7a33 100644 --- a/askbot/skins/default/templates/question.html +++ b/askbot/skins/default/templates/question.html @@ -33,7 +33,7 @@ tags = thread.get_tag_names(), id = 'question-tags', css_class = 'post-tags tags', - tag_css_class = 'post-tag', + tag_css_class = 'post-tag' ) }} {# ==== END: question/question_tags.html" #} diff --git a/askbot/skins/default/templates/user_profile/users_questions.html b/askbot/skins/default/templates/user_profile/users_questions.html index 41809a62..c46e5f82 100644 --- a/askbot/skins/default/templates/user_profile/users_questions.html +++ b/askbot/skins/default/templates/user_profile/users_questions.html @@ -2,7 +2,7 @@ {% import "macros.html" as macros %}
{% for question in questions %} - {{macros.question_summary(question, extra_class='narrow')}} + {{macros.question_summary(question.thread, question, extra_class='narrow')}} {% endfor %}
diff --git a/askbot/skins/default/templates/widgets/question_summary.html b/askbot/skins/default/templates/widgets/question_summary.html index 554dc7f9..d6bd764d 100644 --- a/askbot/skins/default/templates/widgets/question_summary.html +++ b/askbot/skins/default/templates/widgets/question_summary.html @@ -1,22 +1,22 @@ {% from "macros.html" import user_country_flag, tag_list_widget %} -
+
- {{question.thread.view_count|humanize_counter}} + {{thread.view_count|humanize_counter}}
- {% trans cnt=question.thread.view_count %}view{% pluralize %}views{% endtrans %} + {% trans cnt=thread.view_count %}view{% pluralize %}views{% endtrans %}
{{question.thread.answer_count|humanize_counter}}{% if question.thread.accepted_answer %}{% endif %} + >{{thread.answer_count|humanize_counter}}{% if thread.accepted_answer %}{% endif %}
- {% trans cnt=question.thread.answer_count %}answer{% pluralize %}answers{% endtrans %} + {% trans cnt=thread.answer_count %}answer{% pluralize %}answers{% endtrans %}
- {{ question.thread.last_activity_at|diff_date }} + {{ thread.last_activity_at|diff_date }} {% if question.is_anonymous %} - {{ question.thread.last_activity_by.get_anonymous_name() }} + {{ thread.last_activity_by.get_anonymous_name() }} {% else %} - {{question.thread.last_activity_by.username}}{{ user_country_flag(question.thread.last_activity_by) }} - {#{user_score_and_badge_summary(question.thread.last_activity_by)}#} + {{thread.last_activity_by.username}}{{ user_country_flag(thread.last_activity_by) }} + {#{user_score_and_badge_summary(thread.last_activity_by)}#} {% endif %}
-

{{question.get_question_title()|escape}}

- {{ tag_list_widget(question.get_tag_names(), url_params=query_string) }} +

{{thread.get_title()|escape}}

+ {{ tag_list_widget(thread.get_tag_names(), url_params=query_string) }}
diff --git a/askbot/views/readers.py b/askbot/views/readers.py index d08d9bf2..b9de06c5 100644 --- a/askbot/views/readers.py +++ b/askbot/views/readers.py @@ -76,40 +76,22 @@ def questions(request, scope=const.DEFAULT_POST_SCOPE, sort=const.DEFAULT_POST_S List of Questions, Tagged questions, and Unanswered questions. matching search query or user selection """ + if request.method == 'POST': # TODO: This is 405 condition, not 404. Django 1.2+ has decorator for this: https://docs.djangoproject.com/en/1.2/topics/http/decorators/#django.views.decorators.http.require_GET + raise Http404 + #make parameters dictionary params_dict = { 'scope': scope, 'sort': sort, } - if query: - params_dict['query'] = ' '.join(query.split('+')) - if search: - params_dict['search'] = search - if tags: - params_dict['tags'] = ' '.join(tags.split('+')) - if author: - params_dict['author'] = author - if page: - params_dict['page'] = page - if reset_tags: - params_dict['reset_tags'] = reset_tags - if reset_author: - params_dict['reset_author'] = reset_author - if reset_query: - params_dict['reset_query'] = reset_query - if start_over: - params_dict['start_over'] = start_over - if remove_tag: - params_dict['remove_tag'] = remove_tag.decode("utf8") - if page_size: - params_dict['page_size'] = page_size + for arg_name in ('query', 'tags'): + if locals().get(arg_name, None): + params_dict[arg_name] = ' '.join(locals()[arg_name].split('+')) + for arg_name in ('search', 'author', 'page', 'reset_tags', 'reset_author', 'reset_query', 'start_over', 'remove_tag', 'page_size'): + if locals().get(arg_name, None): + params_dict[arg_name] = locals()[arg_name] - #before = datetime.datetime.now() - #don't allow to post to this view - if request.method == 'POST': - raise Http404 #update search state - #form = AdvancedSearchForm(request.GET) form = AdvancedSearchForm(params_dict) if form.is_valid(): user_input = form.cleaned_data @@ -121,32 +103,19 @@ def questions(request, scope=const.DEFAULT_POST_SCOPE, sort=const.DEFAULT_POST_S request.session['search_state'] = search_state request.session.modified = True - #force reset for debugging - #search_state.reset() - #request.session.modified = True - - #todo: have this call implemented for sphinx, mysql and pgsql - (qs, meta_data, related_tags) = models.Thread.objects.run_advanced_search( - request_user = request.user, - search_state = search_state, - ) + qs, meta_data, related_tags = models.Thread.objects.run_advanced_search(request_user=request.user, search_state=search_state) tag_list_type = askbot_settings.TAG_LIST_FORMAT - - #force cloud to sort by name - if tag_list_type == 'cloud': + if tag_list_type == 'cloud': #force cloud to sort by name related_tags = sorted(related_tags, key = operator.attrgetter('name')) - font_size = extra_tags.get_tag_font_size(related_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) - contributors = models.Question.objects.get_question_and_answer_contributors(page.object_list) + contributors_threads = models.Thread.objects.filter(id__in=[post.thread_id for post in page.object_list]) + contributors = models.Thread.objects.get_thread_contributors(contributors_threads) paginator_context = { 'is_paginated' : (paginator.count > search_state.page_size), @@ -175,17 +144,9 @@ def questions(request, scope=const.DEFAULT_POST_SCOPE, sort=const.DEFAULT_POST_S # 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) - - # Format the url with the QueryDict - context_feed_url = '/feeds/rss/?%s' % rss_query_dict.urlencode() + context_feed_url = '/feeds/rss/?%s' % rss_query_dict.urlencode() # Format the url with the QueryDict - reset_method_count = 0 - if search_state.query: - reset_method_count += 1 - if search_state.tags: - reset_method_count += 1 - if meta_data.get('author_name',None): - reset_method_count += 1 + reset_method_count = len(filter(None, [search_state.query, search_state.tags, meta_data.get('author_name', None)])) if request.is_ajax(): @@ -234,28 +195,13 @@ def questions(request, scope=const.DEFAULT_POST_SCOPE, sort=const.DEFAULT_POST_S 'question_counter': question_counter, 'questions': list(), 'related_tags': list(), - 'faces': list(), + 'faces': [extra_tags.gravatar(contributor, 48) for contributor in contributors], 'feed_url': context_feed_url, 'query_string': search_state.query_string(), 'parameters': search_state.make_parameters(), 'page_size' : search_state.page_size, } - badge_levels = dict(const.BADGE_TYPE_CHOICES) - def pluralize_badge_count(count, level): - return ungettext( - '%(badge_count)d %(badge_level)s badge', - '%(badge_count)d %(badge_level)s badges', - count - ) % { - 'badge_count': count, - 'badge_level': badge_levels[level] - } - - gold_badge_css_class = const.BADGE_CSS_CLASSES[const.GOLD_BADGE], - silver_badge_css_class = const.BADGE_CSS_CLASSES[const.SILVER_BADGE], - bronze_badge_css_class = const.BADGE_CSS_CLASSES[const.BRONZE_BADGE], - for tag in related_tags: tag_data = { 'name': tag.name, @@ -263,8 +209,6 @@ def questions(request, scope=const.DEFAULT_POST_SCOPE, sort=const.DEFAULT_POST_S } ajax_data['related_tags'].append(tag_data) - for contributor in contributors: - ajax_data['faces'].append(extra_tags.gravatar(contributor, 48)) #we render the template #from django.template import RequestContext questions_tpl = get_template('main_page/questions_loop.html', request) @@ -287,45 +231,40 @@ def questions(request, scope=const.DEFAULT_POST_SCOPE, sort=const.DEFAULT_POST_S mimetype = 'application/json' ) - 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), - '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, - 'questions' : page, - 'questions_count' : paginator.count, - 'reset_method_count': reset_method_count, - 'scope': search_state.scope, - 'show_sort_by_relevance': askbot.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' : font_size, - 'tag_filter_strategy_choices': const.TAG_FILTER_STRATEGY_CHOICES, - 'update_avatar_data': schedules.should_update_avatar_data(request), - 'query_string': search_state.query_string(), - 'parameters': search_state.make_parameters(), - 'feed_url': context_feed_url, - } + else: # non-AJAX branch - assert(request.is_ajax() == False) - #ajax request is handled in a separate branch above + 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), + '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, + 'questions' : page, + 'questions_count' : paginator.count, + 'reset_method_count': reset_method_count, + 'scope': search_state.scope, + 'show_sort_by_relevance': askbot.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), + 'tag_filter_strategy_choices': const.TAG_FILTER_STRATEGY_CHOICES, + 'update_avatar_data': schedules.should_update_avatar_data(request), + 'query_string': search_state.query_string(), + 'parameters': search_state.make_parameters(), + 'feed_url': context_feed_url, + } - #before = datetime.datetime.now() - response = render_into_skin('main_page.html', template_data, request) - #after = datetime.datetime.now() - #print after - before - return response + return render_into_skin('main_page.html', template_data, request) def tags(request):#view showing a listing of available tags - plain list -- cgit v1.2.3-1-g7c22