main #12
@ -8,6 +8,8 @@ from flask_migrate import Migrate
|
|||||||
from flask_sqlalchemy import SQLAlchemy
|
from flask_sqlalchemy import SQLAlchemy
|
||||||
from flask_wtf.csrf import CSRFProtect
|
from flask_wtf.csrf import CSRFProtect
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
APP = Flask(__name__, static_folder="static")
|
APP = Flask(__name__, static_folder="static")
|
||||||
db = SQLAlchemy()
|
db = SQLAlchemy()
|
||||||
migrate = Migrate()
|
migrate = Migrate()
|
||||||
@ -46,6 +48,7 @@ def create_app():
|
|||||||
migrate.init_app(APP, db, render_as_batch=True)
|
migrate.init_app(APP, db, render_as_batch=True)
|
||||||
bcrypt.init_app(APP)
|
bcrypt.init_app(APP)
|
||||||
|
|
||||||
|
|
||||||
@APP.context_processor
|
@APP.context_processor
|
||||||
def inject_title():
|
def inject_title():
|
||||||
return dict(title=APP.config["title"])
|
return dict(title=APP.config["title"])
|
||||||
|
@ -4,3 +4,7 @@ from flask_wtf import FlaskForm
|
|||||||
from wtforms import StringField, SubmitField, validators
|
from wtforms import StringField, SubmitField, validators
|
||||||
from wtforms.validators import Length
|
from wtforms.validators import Length
|
||||||
from wtforms.widgets import TextArea
|
from wtforms.widgets import TextArea
|
||||||
|
|
||||||
|
class SearchForm(FlaskForm):
|
||||||
|
searchfield = StringField("Search distribusi-verse archive")
|
||||||
|
submit = SubmitField("Search")
|
||||||
|
@ -1,8 +1,41 @@
|
|||||||
import os
|
import os
|
||||||
|
from flask import Blueprint, render_template
|
||||||
from whoosh.fields import *
|
from whoosh.fields import *
|
||||||
from whoosh.index import open_dir
|
from whoosh.index import open_dir
|
||||||
from whoosh.qparser import QueryParser
|
from whoosh.qparser import QueryParser
|
||||||
|
from search.forms.searchform import SearchForm
|
||||||
|
|
||||||
|
searchpages = Blueprint(
|
||||||
|
"search",
|
||||||
|
__name__,
|
||||||
|
template_folder="templates/search",
|
||||||
|
static_folder="static",
|
||||||
|
)
|
||||||
|
|
||||||
SCRIPT_DIR = os.path.dirname(__file__)
|
SCRIPT_DIR = os.path.dirname(__file__)
|
||||||
DATA_DIR = os.path.abspath(os.path.join(SCRIPT_DIR, "../data"))
|
SEARCH_DATA_DIR = os.path.abspath(os.path.join(SCRIPT_DIR, "searchdata"))
|
||||||
|
|
||||||
|
@searchpages.route("/", methods=["GET", "POST"])
|
||||||
|
def searchpage():
|
||||||
|
searchform = SearchForm()
|
||||||
|
found_distribusis = []
|
||||||
|
if searchform.validate_on_submit():
|
||||||
|
found_distribusis = search(searchform.searchfield.data)
|
||||||
|
template = render_template(
|
||||||
|
"search.html",
|
||||||
|
searchform=searchform,
|
||||||
|
found_distribusis=found_distribusis,
|
||||||
|
)
|
||||||
|
return template
|
||||||
|
|
||||||
|
|
||||||
|
def search(searchinput):
|
||||||
|
"""search and get search result titles and return them as distribusi ids"""
|
||||||
|
ix = open_dir(SEARCH_DATA_DIR)
|
||||||
|
with ix.searcher() as searcher:
|
||||||
|
query = QueryParser("content", ix.schema).parse(searchinput)
|
||||||
|
search_results = searcher.search(query)
|
||||||
|
found_distribusis = []
|
||||||
|
for result in search_results:
|
||||||
|
found_distribusis.append(result["title"])
|
||||||
|
return found_distribusis
|
||||||
|
47
verse/search/search_index.py
Normal file
47
verse/search/search_index.py
Normal file
@ -0,0 +1,47 @@
|
|||||||
|
import os
|
||||||
|
from whoosh.fields import *
|
||||||
|
from whoosh.index import create_in
|
||||||
|
from whoosh.qparser import QueryParser
|
||||||
|
from models.distribusi_model import Distribusis
|
||||||
|
import flask_apscheduler
|
||||||
|
|
||||||
|
|
||||||
|
SCRIPT_DIR = os.path.dirname(__file__)
|
||||||
|
SEARCH_DATA_DIR = os.path.abspath(os.path.join(SCRIPT_DIR, "searchdata"))
|
||||||
|
|
||||||
|
def init_search_index(APP):
|
||||||
|
scheduler = flask_apscheduler.APScheduler()
|
||||||
|
scheduler.api_enabled = False
|
||||||
|
scheduler.init_app(APP)
|
||||||
|
scheduler.start()
|
||||||
|
index_distribusis(APP)
|
||||||
|
index_distribusi_files(APP)
|
||||||
|
|
||||||
|
@scheduler.task("interval", id="update", minutes=60)
|
||||||
|
def update_search_index():
|
||||||
|
index_distribusis(APP)
|
||||||
|
index_distribusi_files(APP)
|
||||||
|
|
||||||
|
|
||||||
|
def index_distribusis(APP):
|
||||||
|
schema = Schema(
|
||||||
|
title=TEXT(stored=True), path=ID(stored=True), content=TEXT
|
||||||
|
)
|
||||||
|
ix = create_in(SEARCH_DATA_DIR, schema)
|
||||||
|
writer = ix.writer()
|
||||||
|
distribusis = _visible_distribusis(APP)
|
||||||
|
for distribusi in distribusis:
|
||||||
|
writer.add_document(title=distribusi.distribusiname, path="/a", content=distribusi.description)
|
||||||
|
writer.commit()
|
||||||
|
|
||||||
|
|
||||||
|
def index_distribusi_files(APP):
|
||||||
|
APP.logger.info("searching distribusi files not implemented yet.")
|
||||||
|
|
||||||
|
|
||||||
|
def _visible_distribusis(APP):
|
||||||
|
with APP.app_context():
|
||||||
|
distribusis = Distribusis.query.filter(
|
||||||
|
Distribusis.visible.isnot(False)
|
||||||
|
).all()
|
||||||
|
return distribusis
|
@ -1,3 +1,23 @@
|
|||||||
{% extends "base/base.html" %}
|
{% extends "base/base.html" %}
|
||||||
{% block main %}
|
{% block main %}
|
||||||
|
<div id="distribusiverse" class="maincontent">
|
||||||
|
<form method="POST" enctype="multipart/form-data" action="{{ url_for('search.searchpage') }}">
|
||||||
|
{{ searchform.csrf_token }}
|
||||||
|
<fieldset class="required">
|
||||||
|
{{ searchform.searchfield.label }}
|
||||||
|
{{ searchform.searchfield }}
|
||||||
|
{% for message in searchform.searchfield.errors %}
|
||||||
|
<div class="error">{{ message }}</div>
|
||||||
|
{% endfor %}
|
||||||
|
</fieldset>
|
||||||
|
<fieldset class="button required">
|
||||||
|
{{ searchform.submit }}
|
||||||
|
</fieldset>
|
||||||
|
</form>
|
||||||
|
<div class="searchresults">
|
||||||
|
{% for found_distribusis in found_distribusis %}
|
||||||
|
<p>{{found_distribusis}}</p>
|
||||||
|
{% endfor %}
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
{% endblock %}
|
{% endblock %}
|
||||||
|
@ -26,6 +26,8 @@ from statuspengguna.forgotpassword import forgot_password
|
|||||||
from statuspengguna.helper import UserHelper
|
from statuspengguna.helper import UserHelper
|
||||||
from statuspengguna.loginuser import login_section
|
from statuspengguna.loginuser import login_section
|
||||||
from statuspengguna.registeruser import register_user
|
from statuspengguna.registeruser import register_user
|
||||||
|
from search.search import searchpages
|
||||||
|
from search.search_index import init_search_index
|
||||||
|
|
||||||
APP = create_app()
|
APP = create_app()
|
||||||
stash_page = Blueprint("stash_page", __name__, static_folder="stash")
|
stash_page = Blueprint("stash_page", __name__, static_folder="stash")
|
||||||
@ -36,7 +38,8 @@ APP.register_blueprint(register_user, url_prefix="/register")
|
|||||||
APP.register_blueprint(forgot_password, url_prefix="/login/forgotpassword")
|
APP.register_blueprint(forgot_password, url_prefix="/login/forgotpassword")
|
||||||
APP.register_blueprint(admin_page, url_prefix="/admin")
|
APP.register_blueprint(admin_page, url_prefix="/admin")
|
||||||
APP.register_blueprint(distribusikan, url_prefix="/distribusikan")
|
APP.register_blueprint(distribusikan, url_prefix="/distribusikan")
|
||||||
|
APP.register_blueprint(searchpages, url_prefix="/search")
|
||||||
|
init_search_index(APP)
|
||||||
|
|
||||||
@APP.before_request
|
@APP.before_request
|
||||||
def session_handler():
|
def session_handler():
|
||||||
|
Loading…
Reference in New Issue
Block a user