Python wtforms QuerySelectField:返回除主键条目以外的其他内容

时间:2019-10-07 20:33:05

标签: python flask-wtforms

我正在使用Flask制作网络应用。

简而言之::当我们提交使用QuerySelectField + sqlalchemy查询填充选择框的表单时,所提交的实际值似乎是主键,但是如果我需要提交该怎么办?另一个价值?假设一个表有两列,即ID和Item,现在ID是主键,但是用户不是通过主键ID而是通过Item选择行,这就是他们看到的项名称,而不是主键ID。但是表单提交了ID,我不想提交项目名称。

我觉得很难解释,所以这里是长版

详细解释

我有一个模型,该模型使表的营养价值具有两列,“ id”是主键,“ item”列中包含食物类型的名称。

class nutritionalvalues(db.Model):
    id = db.Column(db.Integer, primary_key=True)
    item = db.Column(db.String(200), nullable=False)

    def __repr__(self):
        return '{}'.format(self.item)

现在使用sqlalchemy和flaskforms

def choice_query():
    return nutritionalvalues.query

class ChoiceForm(FlaskForm):
    item = QuerySelectField(query_factory=choice_query, allow_blank=False)

我制作了类“ ChoiceForm”,并用它来制作表格

form = ChoiceForm()
return render_template('index.html', form=form)

在index.html模板中,我有标记

    <form action="/" method="POST">
        {{ form.csrf_token }}
        {{ form.item }}
        <input type="submit" value="Add Item">
    </form>

在呈现时,浏览器会生成html代码

<form action="/" method="POST">
    <select id="item" name="item">
        <option value="1">&lt;nutritionalvalues 1&gt;</option>
        <option value="2">&lt;nutritionalvalues 2&gt;</option>
        <option value="3">&lt;nutritionalvalues 3&gt;</option>
    </select>
    <input type="submit" value="Add Item">
 </form>

现在说我使用'get_label'参数,我可以将选择选项更改为实际项目

class ChoiceForm(FlaskForm):
    item = QuerySelectField(query_factory=choice_query, allow_blank=False, get_label='item')

因此html呈现如下

<form action="/" method="POST">
    <select id="item" name="item">
        <option value="1">bread</option>
        <option value="2">salmon</option>
        <option value="3">pork</option>
    </select>
    <input type="submit" value="Add Item">
 </form>

但是在提交表单时,选择框为“面包”返回“ 1”,但是我希望它返回“面包”

因为我随后将其用于将此数据输入到另一个表中,如下所示

if request.method == 'POST':
    food_item = request.form['item']
    new_food = eaten(item=food_item)

    try:
        db.session.add(new_food)
        db.session.commit()
        return redirect('/')

我不想输入“ 1”作为我刚吃的食物,我想输入“面包”。

那么提交表单时,如何使用QuerySelectField + sqlalchemy查询工具包将实际的项目名称传递回去?

1 个答案:

答案 0 :(得分:1)

答案非常类似于您对get_label所做的操作,其中get_label要么接受字符串属性名称,要么接受传递给对象以导出对象的一个​​参数标签。

来自documentation

  

在大多数情况下,主键会从   模型,或者将一个可调用参数传递给get_pk,该参数可以   返回唯一的可比较键

有些矛盾的是,get_pk参数不接受字符串属性名称,只能接受一个参数,但是本质上是相同的(将传递给get_label的字符串转换为一个-可使用operator.attrgetter() [source]调用的参数)。因此,您可以通过将可调用对象传递到get_pk,例如get_pk=operator.attrgetter("item")get_pk=lambda x: x.item来控制用于标识所选选项的对象字段,以节省导入。

如果您打算以这种方式使用nutritionalvalues.item,则可能要对其施加唯一约束,以确保在有人添加名称已经存在的项目时,不会出现任何错误。