python - 使用Flask-SQLAlchemy处理表单中的列名以进行更新查询

时间:2018-04-18 16:48:30

标签: python flask sqlalchemy flask-sqlalchemy html-form

我正在使用Flask和SQLAlchemy,我想编写一个HTML表单来执行数据库更新。但是,我希望用户为方便起见构建查询:

select用户选择要修改的列,在input中插入新值,从第二个select中选择where列}子句,在最后一个输入文本中,他插入条件的值。

从逻辑的角度来看,我想到了这样的事情:

exhb = Exhibition.query.filter_by (request.form.get ('wh') = request.form ['cond']). first ()
exhb.request.form.get ('columns') = Request.Form ['val']
db.session.commit ()

但它返回:

SyntaxError: keyword can not be an expression

我尝试使用两个变量来分配whcolumns,但是,虽然正确读取了值,但它会返回我:

Entity '<class' connect.Exhibition '>' has no property 'wh'

如何才能简单地获取要在查询中使用的两列的名称?有没有内置方法可以做到这一点?

2 个答案:

答案 0 :(得分:2)

我建议您先查询数据库,然后将行ID作为select in html

的值

在烧瓶应用

@app.route('/exhibition', methods=['GET', 'POST'])
def exhibition():
    options = session.query(Exhibition) #however you query your db
    return render_template('exhibition.html', options = options)

在你的HTML中(我猜你正在使用jinja进行模板化)

<select>
{%for option in options%}
  <option value={{option.id}}>{{option.text}}</option>
{endfor}
</select>

然后,您可以通过行ID获取要修改的行,这是您在发布表单时获得的行。

然后,当您更新行时,请确保指定要更新的特定列,例如

row_to_edit = session.query(Exhibition).filter_by(id = request.form ['input_field']))
#specify what you are updating
row_to_edit.column_to_update = request.form ['input_field']
# Then you can comit column_to_edit

为了确保编辑人员能够轻松识别列名称,并减轻必须验证与列名称匹配的自由文本条目的负担,我建议您添加第二个显示列名称的选择字段所以自由文本输入只是列值 上面的视图变为

@app.route('/exhibition', methods=['GET', 'POST'])
    def exhibition():
        options = session.query(Exhibition) #however you query your db
        cols = Exhibition.__table__.columns
        return render_template('exhibition.html', options = options, cols = cols)

第二个选择

<select>
{%for col in cols%}
  <option value={{col.key}}>{{col.key}}</option>
{endfor}
</select>

您可以通过迭代cols并提供一个包含值和可读文本的列表来使选项文本更具可读性

指定您正在更新的列

row_to_edit.getattr(row_to_edit, request.form ['select_field_for_column'] = request.form ['input_field_column_value']

我知道第一部分令人困惑。通常你会这样做row_to_edit.column_to_update,但因为在我们的例子中,要更新的列是一个变量,我们使用getattr()来获取col名称等于变量

如果你熟悉wtforms,或者你是一个快速学习者,他们会给你一个更优雅的方式来处理这个

答案 1 :(得分:1)

过滤器调用中的request.form.get()调用会形成一个表达式(see docs),这是不允许的。因此,filter_by()filter()期望等于运算符左侧的关键字参数。

也就是说,如果你在那里放置一个函数调用(在你的情况下为request.form.get()),Python将引发keyword can not be an expression错误。换句话说,您无法直接使用表单请求的结果。

相反,您需要在代码中显式传递关键字参数。鉴于您已在表单中显示了列选项的预设列表,您可以在视图函数中显式处理这组选项,如下所示:

def query_construction_view():
    ....
    wh = request.form.get('wh')
    cond = request.form['cond']
    if wh == 'column_option1':
        exhb = Exhibition.query.filter_by(column_option1=cond)
        ....
    elif wh == 'column_option2':
        exhb = Exhibition.query.filter_by(column_option2=cond)
        ....
    # etc.

请注意每个filter_by()调用中等号的左侧是关键字,而不是函数调用或字符串。另请注意,您可以在右侧使用变量和表达式,即从表单输入中获取的cond参数。

这不是最具扩展性的解决方案,因为关键位是硬编码的。我不知道您的用例是什么,但使用预打包的数据库前端(如Flask-Admin)来处理数据库交互可能会更好。

有关filter()filter_by()的更多信息,请参阅SQLAlchemy Query API

相关问题