【问题标题】:Flask - SQLAlchemy full text searchFlask - SQLAlchemy 全文搜索
【发布时间】:2016-12-13 05:59:57
【问题描述】:

我正在尝试建立一个小型在线植物数据库,并希望加入一个搜索引擎。我正在使用 Flask 构建我的应用程序,并且我使用 SQLAlchemy 和 pymysql 将应用程序连接到 MySQL 数据库。我一直在摆弄 Flask-WhooshAlchemy,到目前为止还没有运气。我想要的是搜索,如果用户搜索特定植物,它将转到植物信息页面或返回相似物种的结果。例如,如果他们要搜索“Carex utriculata”,它会将他们直接带到“Carex utriculata”的物种信息页面。但是,如果他们搜索“Carex”,他们会得到一个列出所有相似物种的结果页面,因此可能会有一个类似“Carex aquatilis”“Carex keloggii”“Carex utriculata”的列表。

到目前为止,在我的尝试中,似乎尝试了搜索,但结果显示了我数据库中的所有植物,而不仅仅是输入搜索的内容。如果它与搜索完全匹配,我什至没有尝试让搜索直接进入单个工厂的页面,因为我一直坚持让搜索工作。我正在使用 Python 3.5。这是我的代码。

初始化.py

import pymysql.cursors
from flask import Flask
from flask_sqlalchemy import SQLAlchemy
import flask_whooshalchemy as whooshalchemy


app = Flask(__name__)


app.config['SQLALCHEMY_DATABASE_URI'] = 'mysql+pymysql://root:passwrd@localhost/restorationplantdb'
app.config['SQLALCHEMY_TRACK_MODIFICATIONS'] = True
app.config['WHOOSE_BASE'] = 'results'


db = SQLAlchemy(app)

class SPInfo(db.Model):
    __tablename__ = 'speciesinfo'
    __searchable__ = ['NRCS_Species', 'NRCS_CommonName']
    speciesinfo_id = db.Column(db.Integer,primary_key=True)
    ID = db.Column(db.Integer)
    MTNHP_Species = db.Column(db.String(45))
    NRCS_Species = db.Column(db.String(45))
    NRCS_CommonName = db.Column(db.String(45))
    Synonyms = db.Column(db.Text)
    Sp_Stratum = db.Column(db.String(12))
    Origin = db.Column(db.String(25))
    Duration = db.Column(db.String(25))
    Habitat = db.Column(db.Text)
    Elevation = db.Column(db.Text)


whooshalchemy.whoosh_index(app, SPInfo)

import RestorationPlantDB.views

views.py

from flask import render_template, url_for, redirect, session, request
from datetime import datetime
from RestorationPlantDB import app
from RestorationPlantDB import db
from RestorationPlantDB import SPInfo



@app.route('/search', methods = ['GET','POST'])
def search():
    results = SPInfo.query.all()
    return render_template('search.html', results=results)

@app.route('/results')
def results():
    results = SPInfo.query.whoosh_search(request.args.get('query')).all()
    return render_template('search.html', results=results)

搜索.html

{% extends "layout.html" %}

{% block content %}


{% for result in results %}
<p>{{ result.NRCS_Species }} - {{ result.NRCS_CommonName }}</p>
{% endfor %}



<div class="col-sm-3 col-sm-offset-1 blog sidebar">
    <div class="sidebar-module sidebar-module-insert">
        <h4>Search</h4>
        <form class="form-inline" method="GET" action="search">
            <div class="form-group">
                <label for="query">Name</label>
                <input type="text" class="form-control" name="query" id="query" />
            </div>
            <button type="submit" class="btn btn-primary">Search</button>
        </form>
    </div>
</div>


{% endblock %}

【问题讨论】:

    标签: flask flask-sqlalchemy whoosh


    【解决方案1】:

    您所做的只是查询所有内容,这就是您得到所有​​内容的原因。您正在过滤/results 下的查询,但表单没有出现在那里。与其像那样将它们分开,您可以轻松地这样做:

    @app.route('/search', methods = ['GET','POST'])
    def search(results=None):
        if request.method == 'POST':
            results = SPInfo.query.whoosh_search(request.form.get('query')).all()
        return render_template('search.html', results=results)
    

    并完全删除/results。接下来,您需要实现重定向到完全匹配。为此,我会将其添加到上面的代码中:

    from sqlalchemy import func
    
    @app.route('/search', methods = ['GET','POST'])
    def search(results=None):
        if request.method == 'POST':
            keywords = request.form.get('query')
            unique_result = SPInfo.query.filter(func.lower(SPInfo.NRCS_Species) == func.lower(keywords)).first() or SPInfo.query.filter(func.lower(SPInfo.NRCS_CommonName) == func.lower(keywords)).first()
            if unique_result:
                #insert return redirect() to specific page using unique_result here
            results = SPInfo.query.whoosh_search(keywords).all()
        return render_template('search.html', results=results)
    

    通常我会这样做:

    unique_result = SPInfo.query.filter_by(NRCS_Species=keywords).first() or SPInfo.query.filter_by(NRCS_CommonName=keywords).first()
    

    但我假设您希望它不区分大小写。如果不这样做,请将查询替换为该查询。

    我也将重定向留空,因为我不知道您的路线在物种页面上是什么样的,但应该不难弄清楚。

    编辑

    更改了函数定义,需要在模板中添加一个小改动,如下所示:

    {% if results %}
        {% for result in results %}
            <p>{{ result.NRCS_Species }} - {{ result.NRCS_CommonName }}</p>
        {% endfor %}
    {% endif %}
    

    【讨论】:

    • 感谢您的回复。我认为这离解决问题越来越近了。但现在它向我抛出了一个错误。 UnboundLocalError:分配前引用的局部变量“结果”。我调查了这个错误,发现其他人经常遇到这个问题,并且讨厌问其他人多次问过的相同问题..但我尝试了一些建议的修复程序,比如尝试使结果全局化。我尝试的修复似乎不起作用。有什么建议可以解决这个错误吗?
    • @DazedAndConfusedNewby 哦,我明白了。您需要做的就是将def search(): 替换为def search(results=None):
    • @DazedAndConfusedNewby 实际上,您可能还需要编辑模板以接受空的结果变量。我会相应地编辑答案。
    • 谢谢。您的编辑修复了 UnboundLocalError。现在它返回搜索但未发布任何结果。这是我运行搜索时的输出。 127.0.0.1 - - [06/Dec/2016 14:24:39] “GET /search?query=Carex+utriculata HTTP/1.1”200 - [搜索页面没有显示结果][1] [1]:i。 stack.imgur.com/U5siX.jpg 我不确定发生了什么。还有什么想法吗?如果我真的需要,我会切换到 postgresql 而不是 MySql,但我希望这不是必需的。
    • @DazedAndConfusedNewby 我有点忙,但今天我有时间研究一下。似乎烧瓶-whooshalchemy 已经过时了,它的开发人员并不是特别活跃。我尝试使用一些分叉版本,但它们也失败了。我一直需要为我的一个项目实现一些搜索功能,所以我会在找到替代解决方案后回复您。
    猜你喜欢
    • 2012-11-01
    • 2018-04-24
    • 2017-07-23
    • 1970-01-01
    • 1970-01-01
    • 2017-07-12
    • 2013-02-04
    • 1970-01-01
    • 2021-10-24
    相关资源
    最近更新 更多