summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorTomasz Zielinski <tomasz.zielinski@pyconsultant.eu>2011-12-27 14:49:42 +0100
committerTomasz Zielinski <tomasz.zielinski@pyconsultant.eu>2011-12-27 14:49:42 +0100
commit1a4e435460bf3ea25a2b03e50eeb5ac67838502c (patch)
tree5aa4d35115a7f23a74127f1bf07e0c23d722186d
parentd008bf1b670388b23f7dc841caba6ca8aa596a1a (diff)
downloadaskbot-1a4e435460bf3ea25a2b03e50eeb5ac67838502c.tar.gz
askbot-1a4e435460bf3ea25a2b03e50eeb5ac67838502c.tar.bz2
askbot-1a4e435460bf3ea25a2b03e50eeb5ac67838502c.zip
questions() view cleanup and conversion to Post
-rw-r--r--askbot/models/question.py53
-rw-r--r--askbot/skins/default/templates/macros.html2
-rw-r--r--askbot/skins/default/templates/main_page.html6
-rw-r--r--askbot/skins/default/templates/main_page/questions_loop.html6
-rw-r--r--askbot/skins/default/templates/question.html2
-rw-r--r--askbot/skins/default/templates/user_profile/users_questions.html2
-rw-r--r--askbot/skins/default/templates/widgets/question_summary.html28
-rw-r--r--askbot/views/readers.py157
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 === #}
+ <div id="question-list">
+ {% include "main_page/questions_loop.html" %}
+ </div>
+ {# ==== 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 %}
<div class="evenMore">
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 %}
<div class="user-stats-table">
{% for question in questions %}
- {{macros.question_summary(question, extra_class='narrow')}}
+ {{macros.question_summary(question.thread, question, extra_class='narrow')}}
{% endfor %}
</div>
<!-- end users_questions.html -->
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 %}
-<div class="short-summary{% if extra_class %} {{extra_class}}{% endif %}" id="question-{{question.id}}">
+<div class="short-summary{% if extra_class %} {{extra_class}}{% endif %}" id="question-{{question.self_question_id}}">
<div class="counts">
<div class="views
- {% if question.thread.view_count == 0 -%}
+ {% if thread.view_count == 0 -%}
no-views
{% else -%}
some-views
{%- endif -%}">
- <span class="item-count">{{question.thread.view_count|humanize_counter}}</span>
+ <span class="item-count">{{thread.view_count|humanize_counter}}</span>
<div>
- {% trans cnt=question.thread.view_count %}view{% pluralize %}views{% endtrans %}
+ {% trans cnt=thread.view_count %}view{% pluralize %}views{% endtrans %}
</div>
</div>
<div class="answers
- {% if question.thread.answer_count == 0 -%}
+ {% if thread.answer_count == 0 -%}
no-answers
{% else -%}
- {%- if question.thread.accepted_answer -%}
+ {%- if thread.accepted_answer -%}
accepted
{%- else -%}
some-answers
@@ -24,9 +24,9 @@
{%- endif -%}">
<span
class="item-count"
- >{{question.thread.answer_count|humanize_counter}}{% if question.thread.accepted_answer %}{% endif %}</span>
+ >{{thread.answer_count|humanize_counter}}{% if thread.accepted_answer %}{% endif %}</span>
<div>
- {% trans cnt=question.thread.answer_count %}answer{% pluralize %}answers{% endtrans %}
+ {% trans cnt=thread.answer_count %}answer{% pluralize %}answers{% endtrans %}
</div>
</div>
<div class="votes
@@ -43,16 +43,16 @@
<div style="clear:both"></div>
<div class="userinfo">
- <span class="relativetime" title="{{question.thread.last_activity_at}}">{{ question.thread.last_activity_at|diff_date }}</span>
+ <span class="relativetime" title="{{thread.last_activity_at}}">{{ thread.last_activity_at|diff_date }}</span>
{% if question.is_anonymous %}
- <span class="anonymous">{{ question.thread.last_activity_by.get_anonymous_name() }}</span>
+ <span class="anonymous">{{ thread.last_activity_by.get_anonymous_name() }}</span>
{% else %}
- <a href="{% url user_profile question.thread.last_activity_by.id, question.thread.last_activity_by.username|slugify %}">{{question.thread.last_activity_by.username}}</a>{{ user_country_flag(question.thread.last_activity_by) }}
- {#{user_score_and_badge_summary(question.thread.last_activity_by)}#}
+ <a href="{% url user_profile thread.last_activity_by.id, thread.last_activity_by.username|slugify %}">{{thread.last_activity_by.username}}</a>{{ user_country_flag(thread.last_activity_by) }}
+ {#{user_score_and_badge_summary(thread.last_activity_by)}#}
{% endif %}
</div>
</div>
- <h2><a title="{{question.summary|escape}}" href="{{ question.get_absolute_url() }}">{{question.get_question_title()|escape}}</a></h2>
- {{ tag_list_widget(question.get_tag_names(), url_params=query_string) }}
+ <h2><a title="{{question.summary|escape}}" href="{{ thread.get_absolute_url() }}">{{thread.get_title()|escape}}</a></h2>
+ {{ tag_list_widget(thread.get_tag_names(), url_params=query_string) }}
</div>
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