使用“短语搜索"在烧瓶管理员 [英] Use a "phrase search" in flask admin

查看:80
本文介绍了使用“短语搜索"在烧瓶管理员的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我正在使用Flask-Admin,对此我感到非常满意.

I am using Flask-Admin and I am very happy with it.

文档显示几个可用于搜索预定义字段的选项.我想允许我的用户使用引号进行搜索,例如:

The docs show several options that can be used to search predefined fields. I want to allow my users to use quotation marks to search, as for instance, in:

"some phrase of which the order should be intact"

如何使用Flask-Admin执行此操作?

How can I do this with Flask-Admin?

推荐答案

在Flask-Admin 1.3.0中,您可以在管理视图类中覆盖_apply_search方法.请参阅下面的非常简单的代码示例-大部分取自Flask-Admin sqla示例app.py.

In Flask-Admin 1.3.0 you can override the _apply_search method in your admin view class. See the very simple code example below - mostly taken from the Flask-Admin sqla example app.py.

基本上,您想为column_searchable_list中的列生成一个类似%Your Phrase Here%的SQL._apply_search的标准行为是在空格上分割搜索输入文本,并为结果数组中的每个术语生成类似SQL的片段.

Essentially, you want to generate an SQL like %Your Phrase Here% for the columns in your column_searchable_list. The standard behaviour of _apply_search is to split the search input text on spaces and generate SQL like fragments for each term in the resultant array.

相反,您可以使用正则表达式查看是否已输入带引号的字符串,提取引号内的短语,创建适当的SQL(如片段),然后将其传递给生成查询的代码.

Instead, you can use a regular expression to see if a quoted string has been entered, extract the phrase within the quotes, create the appropriate SQL like fragment and then pass that on to the code that generates the query.

您还可以执行类似于实现短语过滤的操作-请参见下面的代码中的FilterPhrase类以及如何在column_filters列表定义中使用它.

You can also do something similar to implement phrase filtering - see the class FilterPhrase in the code below and how it is used in the column_filters list definition.

对于更复杂的短语搜索,您可以使用内置短语 Whoosh Postgres的文本搜索的搜索功能(可以与 SQLAlchemy-Searchable ),甚至是

For more sophisticated phrase searching you could use something like Whoosh, the built-in phrase searching capabilities of Postgres text searching (maybe combined with SQLAlchemy-Searchable) or even Elasticsearch.

# coding: utf-8
__author__ = 'Paul'

from flask import Flask
from flask.ext.sqlalchemy import SQLAlchemy
from sqlalchemy import or_
from flask.ext.admin import Admin
from flask.ext.admin.contrib.sqla import ModelView
from flask.ext.admin.babel import lazy_gettext
from flask.ext.admin.contrib.sqla.filters import BaseSQLAFilter
import re

app = Flask(__name__)

app.config['SQLALCHEMY_DATABASE_URI'] = 'sqlite:///:memory:'
app.config['SQLALCHEMY_ECHO'] = True
db = SQLAlchemy(app)


@app.route('/')
def index():
    return '<a href="/admin/">Click me to get to Admin!</a>'


class Post(db.Model):
    id = db.Column(db.Integer, primary_key=True)
    title = db.Column(db.String(255))
    content = db.Column(db.Text, nullable=False)

    def __unicode__(self):
        return self.title


class FilterPhrase(BaseSQLAFilter):
    def apply(self, query, value, alias=None):
        stmt = "%{phrase}%".format(phrase=value)
        return query.filter(self.get_column(alias).ilike(stmt))

    def operation(self):
        return lazy_gettext('phrase')


class PostAdmin(ModelView):
    column_searchable_list = ['title', 'content']

    column_filters = (
        FilterPhrase(Post.title, "Title"),
        FilterPhrase(Post.content, "Content"),
    )

    def _apply_search(self, query, count_query, joins, count_joins, search):

        phrases = re.findall(r'"([^"]*)"', search)

        if len(phrases) == 0:
            return super(PostAdmin, self)._apply_search(query, count_query, joins, count_joins, search)

        stmt = "%{phrase}%".format(phrase=phrases[0])

        # The code below is taken directly from the base _apply_search
        filter_stmt = []
        count_filter_stmt = []

        for field, path in self._search_fields:
            query, joins, alias = self._apply_path_joins(query, joins, path, inner_join=False)

            count_alias = None

            if count_query is not None:
                count_query, count_joins, count_alias = self._apply_path_joins(count_query,
                                                                               count_joins,
                                                                               path,
                                                                               inner_join=False)

            column = field if alias is None else getattr(alias, field.key)
            filter_stmt.append(column.ilike(stmt))

            if count_filter_stmt is not None:
                column = field if count_alias is None else getattr(count_alias, field.key)
                count_filter_stmt.append(column.ilike(stmt))

        query = query.filter(or_(*filter_stmt))

        if count_query is not None:
            count_query = count_query.filter(or_(*count_filter_stmt))

        return query, count_query, joins, count_joins


# Create admin
admin = Admin(app, name='Phrase Searching')
admin.add_view(PostAdmin(model=Post, session=db.session, category='Blog', name='Posts'))


def build_db():
    sample_posts = [
        {
            'title': "de Finibus Bonorum et Malorum - Part I",
            'content': "Lorem ipsum dolor sit amet, consectetur adipisicing elit, sed do eiusmod tempor incididunt ut"
        },
        {
            'title': "de Finibus Bonorum et Malorum - Part II",
            'content': "Sed ut perspiciatis unde omnis iste natus error sit voluptatem accusantium doloremque"
        },
        {
            'title': "de Finibus Bonorum et Malorum - Part III",
            'content': "At vero eos et accusamus et iusto odio dignissimos ducimus qui blanditiis praesentium"
        }
    ]

    db.drop_all()
    db.create_all()

    for row in sample_posts:
        post = Post(**row)
        db.session.add(post)

    db.session.commit()


if __name__ == '__main__':
    build_db()
    app.run()

这篇关于使用“短语搜索"在烧瓶管理员的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆