Add unified topic search in QueryBuilder

This commit is contained in:
rubenwardy 2019-03-29 19:45:29 +00:00
parent 4c109d6bd3
commit 885209a614
3 changed files with 47 additions and 43 deletions

View File

@ -1,5 +1,5 @@
from .models import db, PackageType, Package, ForumTopic, License, MinetestRelease, PackageRelease from .models import db, PackageType, Package, ForumTopic, License, MinetestRelease, PackageRelease
from .utils import isNo from .utils import isNo, isYes
from sqlalchemy.sql.expression import func from sqlalchemy.sql.expression import func
from flask import abort from flask import abort
from sqlalchemy import or_ from sqlalchemy import or_
@ -28,13 +28,22 @@ class QueryBuilder:
self.lucky = self.random or "lucky" in args self.lucky = self.random or "lucky" in args
self.hide_nonfree = "nonfree" in hide_flags self.hide_nonfree = "nonfree" in hide_flags
self.limit = 1 if self.lucky else None self.limit = 1 if self.lucky else None
self.order_by = args.get("sort") or "score" self.order_by = args.get("sort")
self.order_dir = args.get("order") or "desc" self.order_dir = args.get("order") or "desc"
self.protocol_version = args.get("protocol_version") self.protocol_version = args.get("protocol_version")
self.show_discarded = isYes(args.get("show_discarded"))
self.show_added = args.get("show_added")
if self.show_added is not None:
self.show_added = isYes(self.show_added)
if self.search is not None and self.search.strip() == "": if self.search is not None and self.search.strip() == "":
self.search = None self.search = None
def setSortIfNone(self, name):
if self.order_by is None:
self.order_by = name
def getMinetestVersion(self): def getMinetestVersion(self):
if not self.protocol_version: if not self.protocol_version:
return None return None
@ -59,7 +68,7 @@ class QueryBuilder:
query = query.order_by(func.random()) query = query.order_by(func.random())
else: else:
to_order = None to_order = None
if self.order_by == "score": if self.order_by is None or self.order_by == "score":
to_order = Package.score to_order = Package.score
elif self.order_by == "created_at": elif self.order_by == "created_at":
to_order = Package.created_at to_order = Package.created_at
@ -91,18 +100,31 @@ class QueryBuilder:
return query return query
def buildTopicQuery(self): def buildTopicQuery(self, show_added=False):
topics = ForumTopic.query \ query = ForumTopic.query
.filter(~ db.exists().where(Package.forums==ForumTopic.topic_id)) \
.order_by(db.asc(ForumTopic.wip), db.asc(ForumTopic.name), db.asc(ForumTopic.title)) if not self.show_discarded:
query = query.filter_by(discarded=False)
show_added = self.show_added == True or (self.show_added is None and show_added)
if not show_added:
query = query.filter(~ db.exists().where(Package.forums==ForumTopic.topic_id))
if self.order_by is None or self.order_by == "name":
query = query.order_by(db.asc(ForumTopic.wip), db.asc(ForumTopic.name), db.asc(ForumTopic.title))
elif self.order_by == "views":
query = query.order_by(db.desc(ForumTopic.views))
elif self.order_by == "date":
query = query.order_by(db.asc(ForumTopic.created_at))
sort_by = "date"
if self.search: if self.search:
topics = topics.filter(ForumTopic.title.ilike('%' + self.search + '%')) query = query.filter(ForumTopic.title.ilike('%' + self.search + '%'))
if len(self.types) > 0: if len(self.types) > 0:
topics = topics.filter(ForumTopic.type.in_(self.types)) query = query.filter(ForumTopic.type.in_(self.types))
if self.limit: if self.limit:
topics = topics.limit(self.limit) query = query.limit(self.limit)
return topics return query

View File

@ -20,6 +20,7 @@ from flask_user import *
import flask_menu as menu import flask_menu as menu
from app import app from app import app
from app.models import * from app.models import *
from app.querybuilder import QueryBuilder
@app.route("/todo/") @app.route("/todo/")
@login_required @login_required
@ -55,45 +56,27 @@ def todo_page():
@app.route("/todo/topics/") @app.route("/todo/topics/")
@login_required @login_required
def todo_topics_page(): def todo_topics_page():
query = ForumTopic.query qb = QueryBuilder(request.args)
qb.setSortIfNone("date")
show_discarded = request.args.get("show_discarded") == "True" query = qb.buildTopicQuery()
if not show_discarded:
query = query.filter_by(discarded=False)
total = query.count()
query = query.filter(~ db.exists().where(Package.forums==ForumTopic.topic_id)) \
sort_by = request.args.get("sort")
if sort_by == "name":
query = query.order_by(db.asc(ForumTopic.wip), db.asc(ForumTopic.name), db.asc(ForumTopic.title))
elif sort_by == "views":
query = query.order_by(db.desc(ForumTopic.views))
elif sort_by is None or sort_by == "date":
query = query.order_by(db.asc(ForumTopic.created_at))
sort_by = "date"
total = ForumTopic.query.count()
topic_count = query.count() topic_count = query.count()
search = request.args.get("q")
if search is not None and search.strip() != "":
query = query.filter(ForumTopic.title.ilike('%' + search + '%'))
page = int(request.args.get("page") or 1) page = int(request.args.get("page") or 1)
num = int(request.args.get("n") or 100) num = int(request.args.get("n") or 100)
if num > 100 and not current_user.rank.atLeast(UserRank.EDITOR): if num > 100 and not current_user.rank.atLeast(UserRank.EDITOR):
num = 100 num = 100
query = query.paginate(page, num, True) query = query.paginate(page, num, True)
next_url = url_for("todo_topics_page", page=query.next_num, query=search, \ next_url = url_for("todo_topics_page", page=query.next_num, query=qb.search, \
show_discarded=show_discarded, n=num, sort=sort_by) \ show_discarded=qb.show_discarded, n=num, sort=qb.order_by) \
if query.has_next else None if query.has_next else None
prev_url = url_for("todo_topics_page", page=query.prev_num, query=search, \ prev_url = url_for("todo_topics_page", page=query.prev_num, query=qb.search, \
show_discarded=show_discarded, n=num, sort=sort_by) \ show_discarded=qb.show_discarded, n=num, sort=qb.order_by) \
if query.has_prev else None if query.has_prev else None
return render_template("todo/topics.html", topics=query.items, total=total, \ return render_template("todo/topics.html", topics=query.items, total=total, \
topic_count=topic_count, query=search, show_discarded=show_discarded, \ topic_count=topic_count, query=qb.search, show_discarded=qb.show_discarded, \
next_url=next_url, prev_url=prev_url, page=page, page_max=query.pages, \ next_url=next_url, prev_url=prev_url, page=page, page_max=query.pages, \
n=num, sort_by=sort_by) n=num, sort_by=qb.order_by)

View File

@ -40,10 +40,9 @@ def api_package_page(package):
@app.route("/api/topics/") @app.route("/api/topics/")
def api_topics_page(): def api_topics_page():
query = ForumTopic.query \ qb = QueryBuilder(request.args)
.order_by(db.asc(ForumTopic.wip), db.asc(ForumTopic.name), db.asc(ForumTopic.title)) query = qb.buildTopicQuery(show_added=True)
pkgs = [t.getAsDictionary() for t in query.all()] return jsonify([t.getAsDictionary() for t in query.all()])
return jsonify(pkgs)
@app.route("/api/topic_discard/", methods=["POST"]) @app.route("/api/topic_discard/", methods=["POST"])