Browse Source

Kill n+1 queries in forum view

Peter Justin 7 years ago
parent
commit
5c6fdde73e
3 changed files with 15 additions and 5 deletions
  1. 11 1
      flaskbb/forum/models.py
  2. 1 1
      flaskbb/templates/forum/forum.html
  3. 3 3
      flaskbb/utils/helpers.py

+ 11 - 1
flaskbb/forum/models.py

@@ -1112,19 +1112,29 @@ class Forum(db.Model, CRUDMixin):
         :param per_page: How many topics per page should be shown
         """
         if user.is_authenticated:
+            # Now thats intersting - if i don't do the add_entity(Post)
+            # the n+1 still exists when trying to access 'topic.last_post'
+            # but without it it will fire another query.
+            # This way I don't have to use the last_post object when I
+            # iterate over the result set.
             topics = Topic.query.filter_by(forum_id=forum_id).\
                 outerjoin(TopicsRead,
                           db.and_(TopicsRead.topic_id == Topic.id,
                                   TopicsRead.user_id == user.id)).\
+                outerjoin(Post, Topic.last_post_id == Post.id).\
+                add_entity(Post).\
                 add_entity(TopicsRead).\
                 order_by(Topic.important.desc(), Topic.last_updated.desc()).\
                 paginate(page, per_page, True)
         else:
             topics = Topic.query.filter_by(forum_id=forum_id).\
+                outerjoin(Post, Topic.last_post_id == Post.id).\
+                add_entity(Post).\
                 order_by(Topic.important.desc(), Topic.last_updated.desc()).\
                 paginate(page, per_page, True)
 
-            topics.items = [(topic, None) for topic in topics.items]
+            topics.items = [(topic, last_post, None)
+                            for topic, last_post, in topics.items]
 
         return topics
 

+ 1 - 1
flaskbb/templates/forum/forum.html

@@ -52,7 +52,7 @@
                 <div class="col-md-3 col-sm-3 col-xs-4 topic-last-post">{% trans %}Last Post{% endtrans %}</div>
             </div>
 
-            {% for topic, topicread in topics.items %}
+            {% for topic, last_post, topicread in topics.items %}
             <div class="row forum-row hover clearfix">
 
                 <div class="col-md-5 col-sm-5 col-xs-8 topic-info">

+ 3 - 3
flaskbb/utils/helpers.py

@@ -298,7 +298,7 @@ def topic_is_unread(topic, topicsread, user, forumsread=None):
         return False
 
     # check read_cutoff
-    if topic.last_post.date_created < read_cutoff:
+    if topic.last_updated < read_cutoff:
         return False
 
     # topicsread is none if the user has marked the forum as read
@@ -306,14 +306,14 @@ def topic_is_unread(topic, topicsread, user, forumsread=None):
     if topicsread is None:
         # user has cleared the forum - check if there is a new post
         if forumsread and forumsread.cleared is not None:
-            return forumsread.cleared < topic.last_post.date_created
+            return forumsread.cleared < topic.last_updated
 
         # user hasn't read the topic yet, or there is a new post since the user
         # has marked the forum as read
         return True
 
     # check if there is a new post since the user's last topic visit
-    return topicsread.last_read < topic.last_post.date_created
+    return topicsread.last_read < topic.last_updated
 
 
 def mark_online(user_id, guest=False):  # pragma: no cover