diff --git a/app/blueprints/homepage/__init__.py b/app/blueprints/homepage/__init__.py index 7e22d804..0750353a 100644 --- a/app/blueprints/homepage/__init__.py +++ b/app/blueprints/homepage/__init__.py @@ -3,7 +3,7 @@ from flask import Blueprint, render_template, redirect bp = Blueprint("homepage", __name__) from app.models import * -from sqlalchemy.orm import joinedload, subqueryload +from sqlalchemy.orm import joinedload, subqueryload, contains_eager from sqlalchemy.sql.expression import func @@ -45,6 +45,13 @@ def home(): joinedload(Package.license), joinedload(Package.media_license)) + def review_load(query): + return query.options( + joinedload(PackageReview.author), + joinedload(PackageReview.thread).joinedload(Thread.first_reply), + joinedload(PackageReview.package).joinedload(Package.author).load_only(User.username, User.display_name), + joinedload(PackageReview.package).load_only(Package.title, Package.name).subqueryload(Package.main_screenshot)) + query = Package.query.filter_by(state=PackageState.APPROVED) count = query.count() @@ -64,7 +71,7 @@ def home(): .limit(20)).all() updated = updated[:4] - reviews = PackageReview.query.filter_by(recommends=True).order_by(db.desc(PackageReview.created_at)).limit(5).all() + reviews = review_load(PackageReview.query.filter_by(recommends=True).order_by(db.desc(PackageReview.created_at))).limit(5).all() downloads_result = db.session.query(func.sum(Package.downloads)).one_or_none() downloads = 0 if not downloads_result or not downloads_result[0] else downloads_result[0] diff --git a/app/blueprints/packages/reviews.py b/app/blueprints/packages/reviews.py index aae705d8..427e48d9 100644 --- a/app/blueprints/packages/reviews.py +++ b/app/blueprints/packages/reviews.py @@ -66,7 +66,7 @@ def review(package): if request.method == "GET" and review: form.title.data = review.thread.title form.recommends.data = "yes" if review.recommends else "no" - form.comment.data = review.thread.replies[0].comment + form.comment.data = review.thread.first_reply.comment # Validate and submit elif can_review and form.validate_on_submit(): @@ -99,7 +99,7 @@ def review(package): thread.replies.append(reply) else: - reply = thread.replies[0] + reply = thread.first_reply reply.comment = form.comment.data thread.title = form.title.data diff --git a/app/blueprints/threads/__init__.py b/app/blueprints/threads/__init__.py index 72f7ad0e..abce922a 100644 --- a/app/blueprints/threads/__init__.py +++ b/app/blueprints/threads/__init__.py @@ -154,7 +154,7 @@ def delete_reply(id): if reply is None or reply.thread != thread: abort(404) - if thread.replies[0] == reply: + if thread.first_reply == reply: flash(gettext("Cannot delete thread opening post!"), "danger") return redirect(thread.getViewURL()) diff --git a/app/models/threads.py b/app/models/threads.py index 95e87dae..3190c044 100644 --- a/app/models/threads.py +++ b/app/models/threads.py @@ -55,8 +55,12 @@ class Thread(db.Model): watchers = db.relationship("User", secondary=watchers, backref="watching") + first_reply = db.relationship("ThreadReply", uselist=False, foreign_keys="ThreadReply.thread_id", + lazy=True, order_by=db.asc("id"), viewonly=True, + primaryjoin="Thread.id==ThreadReply.thread_id") + def get_description(self): - comment = self.replies[0].comment.replace("\r\n", " ").replace("\n", " ").replace(" ", " ") + comment = self.first_reply.comment.replace("\r\n", " ").replace("\n", " ").replace(" ", " ") if len(comment) > 100: return comment[:97] + "..." else: @@ -156,7 +160,7 @@ class ThreadReply(db.Model): return user.rank.atLeast(UserRank.NEW_MEMBER if user == self.author else UserRank.MODERATOR) and not self.thread.locked elif perm == Permission.DELETE_REPLY: - return user.rank.atLeast(UserRank.MODERATOR) and self.thread.replies[0] != self + return user.rank.atLeast(UserRank.MODERATOR) and self.thread.first_reply != self else: raise Exception("Permission {} is not related to threads".format(perm.name)) @@ -201,7 +205,7 @@ class PackageReview(db.Model): "unhelpful": neg, }, "title": self.thread.title, - "comment": self.thread.replies[0].comment, + "comment": self.thread.first_reply.comment, } if include_package: ret["package"] = self.package.getAsDictionaryKey() diff --git a/app/templates/macros/reviews.html b/app/templates/macros/reviews.html index 62ff518d..972b30d9 100644 --- a/app/templates/macros/reviews.html +++ b/app/templates/macros/reviews.html @@ -38,7 +38,7 @@ {% endif %} {% if review.thread %} - {% set reply = review.thread.replies[0] %} + {% set reply = review.thread.first_reply %}
{{ _("Deleting is permanent") }}
diff --git a/app/templates/threads/user_comments.html b/app/templates/threads/user_comments.html index 2e5eaa53..b2f44d06 100644 --- a/app/templates/threads/user_comments.html +++ b/app/templates/threads/user_comments.html @@ -36,7 +36,7 @@ {% endif %} - {% if r == r.thread.replies[0] %} + {% if r == r.thread.first_reply %} {{ r.thread.title }}