Python Flask多参数如何在从一个url查询数据库的多个列时避免多个if语句

Python Flask多参数如何在从一个url查询数据库的多个列时避免多个if语句,python,flask,sqlalchemy,Python,Flask,Sqlalchemy,我正在尝试使用flask作为前端构建一个会计数据库。主页是分类账,有九列“日期”“说明”“借方”“贷方”“金额”“科目”“参考”“日记账”和“年度”,我需要能够一次查询两个,有时两个,有8000多个分录,并且不断增加。到目前为止,我的代码显示了所有的行,一次200行,分页,我读过关于可读代码的“PEP8”,我读过这个和这个,喜欢使用 request.args.get 但是我需要显示所有的行,直到我查询为止,我也看到了这一点,我想也许我可以为每个查询使用一个函数,并在视图函数的外侧使用“If”,然

我正在尝试使用flask作为前端构建一个会计数据库。主页是分类账,有九列“日期”“说明”“借方”“贷方”“金额”“科目”“参考”“日记账”和“年度”,我需要能够一次查询两个,有时两个,有8000多个分录,并且不断增加。到目前为止,我的代码显示了所有的行,一次200行,分页,我读过关于可读代码的“PEP8”,我读过这个和这个,喜欢使用

request.args.get

但是我需要显示所有的行,直到我查询为止,我也看到了这一点,我想也许我可以为每个查询使用一个函数,并在视图函数的外侧使用“If”,然后在视图函数中调用每个行,但我不确定怎么做。或者我可以为每个查询使用一个视图函数。但我不确定这将如何工作,这是我目前的代码

@bp.route('/books', methods=['GET', 'POST'])
@bp.route('/books/<int:page_num>', methods=['GET', 'POST'])
@bp.route('/books/<int:page_num>/<int:id>', methods=['GET', 'POST'])
@bp.route('/books/<int:page_num>/<int:id>/<ref>', methods=['GET', 'POST'])
@login_required
def books(page_num, id=None, ref=None):
    if ref is not None:
        books = Book.query.order_by(Book.date.desc()).filter(Book.REF==ref).paginate(per_page=100, page=page_num, error_out=True)
    else:
        books = Book.query.order_by(Book.date.desc()).paginate(per_page=100, page=page_num, error_out=True)
    if id is not None:
        obj = Book.query.get(id) or Book()
        form = AddBookForm(request.form, obj=obj)
        if form.validate_on_submit():
            form.populate_obj(obj)
            db.session.add(obj)
            db.session.commit()
            return redirect(url_for('books.books'))
    else:
        form = AddBookForm()
        if form.validate_on_submit():
            obj = Book(id=form.id.data, date=form.date.data, description=form.description.data, debit=form.debit.data,\
                  credit=form.credit.data, montant=form.montant.data, AUX=form.AUX.data, TP=form.TP.data,\
                      REF=form.REF.data, JN=form.JN.data, PID=form.PID.data, CT=form.CT.data)
            db.session.add(obj)
            db.session.commit()
            return redirect(url_for('books.books', page_num=1))
    return render_template('books/books.html', title='Books', books=books, form=form)
每个查询都有一个简单的表单,它可以处理每个查询。以下是表单和html代码:

class SearchAuxForm(FlaskForm):
    selectaux = QuerySelectField('Aux', query_factory=AUX, get_label='id')
    submitaux = SubmitField('submit')
def AUX():
    return Auxilliere.query

html:
   <div class="AUX">
        <form action="{{ url_for('books.search_aux') }}" method="post">
            {{ aux_form.selectaux(class="input") }}{{ aux_form.submitaux(class="submit") }}
        </form>
    </div>
class SearchAuxForm(烧瓶形式):
selectaux=QuerySelectField('Aux',query\u factory=Aux,get\u label='id'))
submitaux=SubmitField('submit')
def AUX():
返回辅助查询
html:
{{aux_form.selectaux(class=“input”)}{{{aux_form.submitaux(class=“submit”)}
我试着用一个提交按钮作为一个单一的功能来完成这项工作,但最终以失败告终。我没有将此作为答案提交,因为它并没有满足我的所有要求,但它只是一个开始

最终编辑:


我要感谢重新提出这个问题的人,他让Lucas Scott先生提供了一个引人入胜且信息丰富的答案,以帮助我和其他人。

有很多方法可以实现查询/筛选表中多个列的预期结果。我将给出一个示例,说明如何创建一个端点,使您能够对一列或多列进行筛选

这是我们的基本
Books
模型和作为存根的
/Books
端点

导入烧瓶
从flask_sqlalchemy导入sqlalchemy
app=烧瓶。烧瓶(\uuuuu名称\uuuuuuu)
db=SQLAlchemy(app)#默认情况下使用内存中的sqlite3db
教材(db.Model):
__tablename_u=“book”
id=db.Column(db.Integer,主键=True,自动递增=True)
title=db.Column(db.String(255),null=False)
author=db.Column(db.String(255),null=False)
supplier=db.Column(db.String(255))
published=db.Column(db.Date,nullable=False)
db.create_all()
@app.routes(“/books”,methods=[“GET”])
定义所有书籍():
通过
第一步是决定使用url参数查询集合的方法。我将使用一个事实,即查询参数中同一个键的多个实例作为列表提供,以允许我们对多个列进行筛选

例如,
/books?filter=id&filter=author
将变成
{“filter”:[“id”,“author”]}

对于查询语法,我们将使用逗号分隔的值作为过滤器值

例如:

books?filter=author,eq,jim&suplier,eq,自行出版

它变成了
{“filter”:[“author,eq,jim”,“supplier,eq,self-published”]}
。请注意
自发布
中的空格。flask将为我们处理url编码,并返回一个带有空格的字符串,而不是
%20

让我们通过添加一个
Filter
类来表示我们的
Filter
查询参数,来清理一下这个问题

class QueryValidationError(异常):
“”“我们可以处理特定的异常和
返回带有“”的http响应
通过
类别筛选器:
支持的_运算符=(“eq”、“ne”、“lt”、“gt”、“le”、“ge”)
定义初始化(self、列、运算符、值):
self.column=列
self.operator=运算符
自我价值=价值
self.validate()
def验证(自我):
如果运算符不在自支持的_运算符中:
#我们将在稍后处理此问题
升起QueryValidationError(
f“运算符`{operator}`不受支持”
f“运算符`{self.supported_运算符}”
)
现在,我们将创建一个函数,用于将过滤器列表处理为
Filter
对象列表

def创建过滤器(过滤器):
过滤器\u已处理=[]
如果过滤器为无:
#没有给出过滤器
已处理的返回筛选器
elif isinstance(过滤器、str):
#如果只给出一个过滤器
filter\u split=filters.split(“,”)
过滤器\u已处理。追加(
过滤器(*过滤器分割)
)
elif isinstance(过滤器、列表):
#如果给定了多个过滤器
尝试:
filters\u processed=[Filter(*\u Filter.split(“,”)用于过滤器中的过滤器]
除例外情况外:
引发QueryValidationError(“筛选器查询无效”)
其他:
#程序错误
提高打字错误(
f“过滤器应为`str`或list”
f“但属于类型`{type(filters)}`”
)
已处理的返回筛选器
现在我们可以将助手函数添加到端点

@app.route(“/books”,methods=[“GET”])
定义所有书籍():
args=flask.request.args
过滤器=创建过滤器(args.get(“过滤器”))
SQLAlchemy允许我们使用操作符重载进行过滤。这是使用
过滤器(Book.author==“some value”)
。此处的
=
不会触发默认的
=
行为。相反,SQLAlchemy的创建者重载了这个操作符,它创建了一个SQL查询来检查相等性并将其添加到 查询我们可以通过使用Pythons模块来利用这种行为。例如:

导入操作符
从模型导入书
作者=Book.que
class SearchAuxForm(FlaskForm):
    selectaux = QuerySelectField('Aux', query_factory=AUX, get_label='id')
    submitaux = SubmitField('submit')
def AUX():
    return Auxilliere.query

html:
   <div class="AUX">
        <form action="{{ url_for('books.search_aux') }}" method="post">
            {{ aux_form.selectaux(class="input") }}{{ aux_form.submitaux(class="submit") }}
        </form>
    </div>
def filter_query(filters, query, model):
    for _filter in filters:
        # get our operator
        op = getattr(operator, _filter.operator)
        # get the column to filter on
        column = getattr(model, _filter.column)
        # value to filter for
        value = _filter.value

        # build up a query by adding multiple filters
        query = query.filter(op(column, value))

    return query