From e14d3c8f24ba2595565226ffcc13b4788708cd14 Mon Sep 17 00:00:00 2001 From: Evgeny Fadeev Date: Sun, 4 Mar 2012 02:13:35 -0300 Subject: 9 queries left on the question page logged in with warm cache vs 1 for logged out --- askbot/models/__init__.py | 18 +++++- askbot/models/question.py | 9 ++- askbot/skins/default/templates/macros.html | 43 +++++++------ .../templates/meta/html_head_javascript.html | 2 + askbot/skins/default/templates/question.html | 70 ++++++++++++++++++++++ .../default/templates/question/javascript.html | 4 +- askbot/tasks.py | 14 ++--- askbot/views/readers.py | 25 ++++++-- askbot/views/writers.py | 2 +- 9 files changed, 142 insertions(+), 45 deletions(-) diff --git a/askbot/models/__init__.py b/askbot/models/__init__.py index ae084845..60ff5fb3 100644 --- a/askbot/models/__init__.py +++ b/askbot/models/__init__.py @@ -15,6 +15,7 @@ from django.utils.safestring import mark_safe from django.db import models from django.conf import settings as django_settings from django.contrib.contenttypes.models import ContentType +from django.core import cache from django.core import exceptions as django_exceptions from django_countries.fields import CountryField from askbot import exceptions as askbot_exceptions @@ -499,7 +500,7 @@ def user_can_post_comment(self, parent_post = None): """ if self.reputation >= askbot_settings.MIN_REP_TO_LEAVE_COMMENTS: return True - if self == parent_post.author: + if parent_post and self == parent_post.author: return True if self.is_administrator_or_moderator(): return True @@ -2515,7 +2516,8 @@ def record_user_visit(user, timestamp, **kwargs): context_object = user, timestamp = timestamp ) - user.save() + #somehow it saves on the query as compared to user.save() + User.objects.filter(id = user.id).update(last_seen = timestamp) def record_vote(instance, created, **kwargs): @@ -2700,9 +2702,21 @@ def update_user_avatar_type_flag(instance, **kwargs): def make_admin_if_first_user(instance, **kwargs): + """first user automatically becomes an administrator + the function is run only once in the interpreter session + """ + import sys + #have to check sys.argv to satisfy the test runner + #which fails with the cache-based skipping + #for real the setUp() code in the base test case must + #clear the cache!!! + if 'test' not in sys.argv and cache.cache.get('admin-created'): + #no need to hit the database every time! + return user_count = User.objects.all().count() if user_count == 0: instance.set_admin_status() + cache.cache.set('admin-created', True) #signal for User model save changes django_signals.pre_save.connect(make_admin_if_first_user, sender=User) diff --git a/askbot/models/question.py b/askbot/models/question.py index f6a7e69b..0d76a642 100644 --- a/askbot/models/question.py +++ b/askbot/models/question.py @@ -458,7 +458,6 @@ class Thread(models.Model): all (both posts and the comments sorted in the correct order) """ - print "cache miss!!!" thread_posts = self.posts.all().order_by( { "latest":"-added_at", @@ -470,14 +469,14 @@ class Thread(models.Model): answers = list() post_map = dict() comment_map = dict() - post_id_list = list() + post_to_author = dict() question_post = None for post in thread_posts: #pass through only deleted question posts if post.deleted and post.post_type != 'question': continue - post_id_list.append(post.id) + post_to_author[post.id] = post.author_id if post.post_type == 'answer': answers.append(post) @@ -508,7 +507,7 @@ class Thread(models.Model): answers.remove(self.accepted_answer) answers.insert(0, self.accepted_answer) - return (question_post, answers, post_id_list) + return (question_post, answers, post_to_author) def get_similarity(self, other_thread = None): @@ -568,7 +567,7 @@ class Thread(models.Model): def get_cached_data(): key = 'similar-threads-%s' % self.id data = cache.cache.get(key) - if not data: + if data is None: data = get_data() cache.cache.set(key, data) return data diff --git a/askbot/skins/default/templates/macros.html b/askbot/skins/default/templates/macros.html index 2f3ea879..b5c052cc 100644 --- a/askbot/skins/default/templates/macros.html +++ b/askbot/skins/default/templates/macros.html @@ -236,27 +236,22 @@ poor design of the data or methods on data objects #} {# Warning! Any changes to the comment markup here must be duplicated in post.js for the purposes of the AJAX comment editor #} -{%- macro add_or_show_comments_button(post = None, can_post = None, max_comments = None, widget_id = None) -%} +{%- macro add_or_show_comments_button(post = None, max_comments = None, widget_id = None) -%} + {% if post.comment_count > max_comments %} + {% set remaining_comment_count = post.comment_count - max_comments %} + {% else %} + {% set remaining_comment_count = 0 %} + {% endif %} + - {% if post.comment_count > max_comments %} - {% set remaining_comments = post.comment_count - max_comments %} - - {% if can_post %} - {% trans %}post a comment{% endtrans %} / - {% trans counter=remaining_comments %}see {{counter}} more{% pluralize %}see {{counter}} more{% endtrans %} - {% else %} - {% trans counter=remaining_comments %}see {{counter}} more comment{% pluralize %}see {{counter}} more comments - {% endtrans %} - {% endif %} - - {% elif can_post %} - {% trans %}post a comment{% endtrans %} - {% endif %} {%- endmacro -%} {%- macro post_comments_widget( @@ -298,26 +293,32 @@ for the purposes of the AJAX comment editor #}
{% endif %} -
+
{{comment.html}} {{comment.author.username}}  ({{comment.added_at|diff_date}}) -  {% trans %}edit{% endtrans %} +  {% trans %}edit{% endtrans %}
+ {% endfor %}
- {% set can_post = True %} {% if show_post == post and show_comment %} {% if show_comment_position > max_comments %} {{ add_or_show_comments_button( post = post, - can_post = can_post, max_comments = show_comment_position, widget_id = widget_id ) @@ -326,7 +327,6 @@ for the purposes of the AJAX comment editor #} {{ add_or_show_comments_button( post = post, - can_post = can_post, max_comments = max_comments, widget_id = widget_id ) @@ -336,7 +336,6 @@ for the purposes of the AJAX comment editor #} {{ add_or_show_comments_button( post = post, - can_post = can_post, max_comments = max_comments, widget_id = widget_id ) diff --git a/askbot/skins/default/templates/meta/html_head_javascript.html b/askbot/skins/default/templates/meta/html_head_javascript.html index 58f6430d..65d0bdce 100644 --- a/askbot/skins/default/templates/meta/html_head_javascript.html +++ b/askbot/skins/default/templates/meta/html_head_javascript.html @@ -9,8 +9,10 @@ request.user.is_administrator() or request.user.is_moderator() %}true{% else %}false{% endif %}; + askbot['data']['userReputation'] = {{request.user.reputation}}; {% else %} askbot['data']['userIsAuthenticated'] = false; + askbot['data']['userReputation'] = 0; {% endif %} askbot['urls'] = {}; askbot['settings'] = {}; diff --git a/askbot/skins/default/templates/question.html b/askbot/skins/default/templates/question.html index f25496b8..e241b9b2 100644 --- a/askbot/skins/default/templates/question.html +++ b/askbot/skins/default/templates/question.html @@ -11,6 +11,7 @@ {% endblock %} {% block forejs %} {% endblock %} diff --git a/askbot/skins/default/templates/question/javascript.html b/askbot/skins/default/templates/question/javascript.html index 8ad3f09c..3a29579d 100644 --- a/askbot/skins/default/templates/question/javascript.html +++ b/askbot/skins/default/templates/question/javascript.html @@ -42,7 +42,7 @@ var answer_sort_tab = "{{ tab_id }}"; $("#" + answer_sort_tab).attr('className',"on"); - Vote.init({{ question.id }}, '{{ thread.title|slugify }}', '{{ question.author.id }}','{{ request.user.id }}'); + Vote.init({{ question.id }}, '{{ thread.title|slugify }}', '{{ question.author_id }}','{{ request.user.id }}'); {% if not thread.closed and request.user.is_authenticated %}initEditor();{% endif %} @@ -53,7 +53,7 @@ } {% if settings.ENABLE_SHARING_GOOGLE %}$.getScript("http://apis.google.com/js/plusone.js"){% endif %} - {% if request.user == question.author %} + {% if request.user.id == question.author_id %} $("#fmanswer_button").click(function() { $("#fmanswer").show(); $("#fmanswer_button").hide(); diff --git a/askbot/tasks.py b/askbot/tasks.py index 5509c613..d94e0a68 100644 --- a/askbot/tasks.py +++ b/askbot/tasks.py @@ -160,8 +160,8 @@ def record_post_update( @task(ignore_result = True) def record_question_visit( - question_post_id = None, - user_id = None, + question_post = None, + user = None, update_view_count = False): """celery task which records question visit by a person updates view counter, if necessary, @@ -169,17 +169,17 @@ def record_question_visit( question visit """ #1) maybe update the view count - question_post = Post.objects.filter( - id = question_post_id - ).select_related('thread')[0] + #question_post = Post.objects.filter( + # id = question_post_id + #).select_related('thread')[0] if update_view_count: question_post.thread.increase_view_count() - if user_id == None: + if user.is_anonymous(): return #2) question view count per user and clear response displays - user = User.objects.get(id = user_id) + #user = User.objects.get(id = user_id) if user.is_authenticated(): #get response notifications user.visit_question(question_post) diff --git a/askbot/views/readers.py b/askbot/views/readers.py index 22f60efa..00d2fd5a 100644 --- a/askbot/views/readers.py +++ b/askbot/views/readers.py @@ -423,8 +423,9 @@ def question(request, id):#refactor - long subroutine. display question body, an logging.debug('answer_sort_method=' + unicode(answer_sort_method)) - #load answers and post id's - updated_question_post, answers, post_id_list = thread.get_cached_post_data( + #load answers and post id's->athor_id mapping + #posts are pre-stuffed with the correctly ordered comments + updated_question_post, answers, post_to_author = thread.get_cached_post_data( sort_method = answer_sort_method, ) question_post.set_cached_comments(updated_question_post.get_cached_comments()) @@ -433,13 +434,19 @@ def question(request, id):#refactor - long subroutine. display question body, an #Post.objects.precache_comments(for_posts=[question_post] + answers, visitor=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_id_list + 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 = [ + id for id in post_to_author if post_to_author[id] == request.user.id + ] #resolve page number and comment number for permalinks show_comment_position = None @@ -479,8 +486,8 @@ def question(request, id):#refactor - long subroutine. display question body, an #2) run the slower jobs in a celery task from askbot import tasks tasks.record_question_visit.delay( - question_post_id = question_post.id, - user_id = request.user.id, + question_post = question_post, + user = request.user, update_view_count = update_view_count ) @@ -513,6 +520,10 @@ def question(request, id):#refactor - long subroutine. display question body, an } ) + user_can_post_comment = ( + request.user.is_authenticated() and request.user.can_post_comment() + ) + data = { 'is_cacheable': is_cacheable, 'page_class': 'question-page', @@ -522,9 +533,11 @@ def question(request, id):#refactor - long subroutine. display question body, an 'answer' : answer_form, 'answers' : page_objects.object_list, 'user_votes': user_votes, + 'user_post_id_list': user_post_id_list, + 'user_can_post_comment': user_can_post_comment,#in general 'tab_id' : answer_sort_method, 'favorited' : favorited, - 'similar_threads' : thread.get_similar_threads(),#todo: cache this? + 'similar_threads' : thread.get_similar_threads(), 'language_code': translation.get_language(), 'paginator_context' : paginator_context, 'show_post': show_post, diff --git a/askbot/views/writers.py b/askbot/views/writers.py index 4c435eea..b7e0984e 100644 --- a/askbot/views/writers.py +++ b/askbot/views/writers.py @@ -484,7 +484,7 @@ def answer(request, id):#process a new answer """ question = get_object_or_404(models.Post, post_type='question', id=id) if request.method == "POST": - form = forms.AnswerForm(question, request.user, request.POST) + form = forms.AnswerForm(request.POST) if form.is_valid(): wiki = form.cleaned_data['wiki'] text = form.cleaned_data['text'] -- cgit v1.2.3-1-g7c22