Browse Source

initial work on flask-whooshalchemy search functionality

Casper Van Gheluwe 11 years ago
parent
commit
5b1c5fddbd

+ 1 - 0
.gitignore

@@ -40,6 +40,7 @@ __pycache__
 *.sublime-workspace
 *.sublime-project
 *.egg-info
+*.iml
 flaskbb/configs/production.py
 flaskbb/configs/development.py
 

+ 10 - 0
flaskbb/app.py

@@ -24,9 +24,11 @@ from flaskbb.auth.views import auth
 from flaskbb.admin.views import admin
 # Import the forum blueprint
 from flaskbb.forum.views import forum
+from flaskbb.forum.models import Post, Topic, Category, Forum
 # extenesions
 from flaskbb.extensions import db, login_manager, mail, cache, redis, \
     debugtoolbar, migrate, themes
+from flask.ext.whooshalchemy import whoosh_index
 # various helpers
 from flaskbb.utils.helpers import format_date, time_since, crop_title, \
     is_online, render_markup, mark_online, forum_is_unread, topic_is_unread, \
@@ -94,6 +96,14 @@ def configure_extensions(app):
     # Flask-And-Redis
     redis.init_app(app)
 
+    # Flask-WhooshAlchemy
+    with app.app_context():
+        whoosh_index(app, Post)
+        whoosh_index(app, Topic)
+        whoosh_index(app, Forum)
+        whoosh_index(app, Category)
+        whoosh_index(app, User)
+
     # Flask-Login
     login_manager.login_view = app.config["LOGIN_VIEW"]
     login_manager.refresh_view = app.config["REAUTH_VIEW"]

+ 1 - 1
flaskbb/configs/default.py

@@ -91,7 +91,7 @@ class DefaultConfig(object):
     TITLE_LENGTH = 15
 
     # This is really handy if you do not have an redis instance like on windows
-    REDIS_ENABLED = True
+    REDIS_ENABLED = False
     REDIS_HOST = 'localhost'
     REDIS_PORT = 6379
     REDIS_DB = 0

+ 24 - 1
flaskbb/forum/forms.py

@@ -9,10 +9,12 @@
     :license: BSD, see LICENSE for more details.
 """
 from flask.ext.wtf import Form
-from wtforms import TextAreaField, TextField
+import flask.ext.whooshalchemy
+from wtforms import TextAreaField, TextField, BooleanField, FormField, SelectMultipleField
 from wtforms.validators import Required
 
 from flaskbb.forum.models import Topic, Post, Report
+from flaskbb.user.models import User
 
 
 class QuickreplyForm(Form):
@@ -54,3 +56,24 @@ class ReportForm(Form):
     def save(self, user, post):
         report = Report(**self.data)
         return report.save(user, post)
+
+
+class SearchForm(Form):
+    search_types = SelectMultipleField("Search Types", validators=[
+        Required("Please insert at least one search type")], choices=[
+        ('user', 'User'), ('post', 'Post'), ('topic', 'Topic'), ('forum', 'Forum'), ('category', 'Category')
+    ])
+    search_query = TextField("Search Query", validators=[
+        Required(message="Please insert a search query")
+    ])
+
+    def fetch_types(self):
+        return self.search_types.data
+
+    def fetch_results(self):
+        results = {}
+        types = self.fetch_types()
+        for type in types:
+            if type == 'user':
+                results['user'] = User.query.whoosh_search(self.search_query)
+        print(results)

+ 5 - 1
flaskbb/forum/models.py

@@ -134,6 +134,7 @@ class Report(db.Model):
 
 class Post(db.Model):
     __tablename__ = "posts"
+    __searchable__ = ['content', 'username']
 
     id = db.Column(db.Integer, primary_key=True)
     topic_id = db.Column(db.Integer,
@@ -234,6 +235,7 @@ class Post(db.Model):
 
 class Topic(db.Model):
     __tablename__ = "topics"
+    __searchable__ = ['title', 'username']
 
     query_class = TopicQuery
 
@@ -526,6 +528,7 @@ class Topic(db.Model):
 
 class Forum(db.Model):
     __tablename__ = "forums"
+    __searchable__ = ['title', 'description']
 
     id = db.Column(db.Integer, primary_key=True)
     category_id = db.Column(db.Integer, db.ForeignKey("categories.id"),
@@ -640,6 +643,7 @@ class Forum(db.Model):
 
 class Category(db.Model):
     __tablename__ = "categories"
+    __searchable__ = ['title', 'description']
 
     id = db.Column(db.Integer, primary_key=True)
     title = db.Column(db.String(63), nullable=False)
@@ -688,4 +692,4 @@ class Category(db.Model):
         # and finally delete the category itself
         db.session.delete(self)
         db.session.commit()
-        return self
+        return self

+ 19 - 1
flaskbb/forum/views.py

@@ -25,7 +25,7 @@ from flaskbb.utils.permissions import (can_post_reply, can_post_topic,
 from flaskbb.forum.models import (Category, Forum, Topic, Post, ForumsRead,
                                   TopicsRead)
 from flaskbb.forum.forms import (QuickreplyForm, ReplyForm, NewTopicForm,
-                                 ReportForm)
+                                 ReportForm, SearchForm)
 from flaskbb.utils.helpers import get_forums
 from flaskbb.user.models import User
 
@@ -501,3 +501,21 @@ def untrack_topic(topic_id, slug=None):
     current_user.untrack_topic(topic)
     current_user.save()
     return redirect(topic.url)
+
+
+@forum.route("/search", methods=['GET', 'POST'])
+def search_forum():
+
+    if not current_user.is_authenticated():
+        flash("You need to be logged in for that feature.", "danger")
+        return redirect(url_for("forum.index"))
+
+    form = SearchForm()
+    if form.validate_on_submit():
+        result_type = form.fetch_types()
+        result_list = form.fetch_results()
+        return render_template("forum/search_result.html",
+                               type=result_type,
+                               results=result_list)
+    else:
+        return render_template("forum/search.html", form=form)

+ 21 - 0
flaskbb/templates/forum/search.html

@@ -0,0 +1,21 @@
+{% set page_title = "Search Forum" %}
+{% set active_forum_nav=True %}
+
+{% extends theme("layout.html") %}
+
+{% block navigation %}
+{% endblock %}
+
+{% block content %}
+{% from theme("macros.html") import render_field %}
+
+<form class="form" role="form" method="post">
+    {{ form.hidden_tag() }}
+    <h3>Search Forum</h3>
+
+    {{ render_field(form.search_types) }}
+    {{ render_field(form.search_query) }}
+
+    <button type="submit" class="btn btn-success">Search</button>
+</form>
+{% endblock %}

+ 1 - 0
flaskbb/user/models.py

@@ -72,6 +72,7 @@ class Group(db.Model):
 
 class User(db.Model, UserMixin):
     __tablename__ = "users"
+    __searchable__ = ['username', 'email']
 
     id = db.Column(db.Integer, primary_key=True)
     username = db.Column(db.String(15), unique=True, nullable=False)

+ 1 - 0
setup.py

@@ -58,6 +58,7 @@ setup(
         'itsdangerous==0.23',
         'postmarkup==1.2.0',
         'wsgiref==0.1.2',
+        'Flask-WhooshAlchemy==0.55'
     ],
     classifiers=[
         'Development Status :: 4 - Beta',