Flask WTForms SelectField从api数据创建选择

时间:2019-05-27 03:09:11

标签: python flask wtforms

我正在从这样提供的api中获取信息:

{
  "Location": {
    "Units": [
     {
       "id": 1,
       "Item": [
         {
           "Description": "some string value",
           "ID": "some string value"
         },
         {
           "Description": "some string value",
           "ID": "some string value"
         },
         {
           "Description": "some string value",
           "ID": "some string value"
         }
       ]
     },
     {
       "id": 2,
       "Item": [
         {
           "Description": "some string value",
           "ID": "some string value"
         },
         {
           "Description": "some string value",
           "ID": "some string value"
         },
         {
           "Description": "some string value",
           "ID": "some string value"
         }
       ]
     }
    ]
  }
}

我正在为wtform提供一个选择字段:

forms.py

class ReserveForm(Form):
  item = SelectField(
    'Item',
    choices=[],
    coerce=int
  )

我正在将“ Unit.id”的ID作为url变量传递给我的路由:

app.py

@app.route('/reserve/<id>')
def reserve(id):
  data = *my api data in json format*
  form = ReserveForm()
  return render_template('reserve.html', data=data, form=form)

在我看来,我正在打印表格:

<form action="" method="POST">
  {{ form.hidden_tag() }}
  {{ form.item.label() }}
  {{ form.item() }}
</form>

我需要做的是使用“单元”中的“单元”,其ID与url变量中的ID相匹配,作为选择字段的选择。

我无法找到在模板级别向字段添加选择的方法,这是我的首选方法。像这样:

<form action="" method="POST">
  {{ form.hidden_tag() }}
  {{ form.item.label() }}
  {{ form.item(choices=[data.Location.Unit[specific-ID].item]) }}
</form>

我一直在寻找这样的解决方案,因为我对Jinja2最熟悉。

由于我找不到实现该功能的方法,因此我一直在尝试找出如何在路线中创建选择字段选择。这篇文章很有帮助:Dynamic choices WTForms Flask SelectField

但是我的数据结构不同,因为存在一个额外的嵌套层。

我认为我做对了,方法是循环遍历“单元”以查找ID与我的变量匹配的ID,然后将该“单元”分配给变量。然后,我可以像上面链接的文章那样使用循环的键值(我不知道它叫什么或它如何工作,所以我无法搜索它的工作方式):

@app.route('/reserve/<id>')
def reserve(id):
  data = *my api data in json format*
  for item in data['Location']['Unit']:
    if item['ID'] == id:
      unit = item
  items = [(item['ID'], item['Description']) for item in unit['Item']]
  form = ReserveForm()
  form.item.choices = items

  return render_template('reserve.html', data=data, form=form)

我很确定这是可行的,但是我收到一个错误“ alueError:int()以10为底的无效文字:”

很显然,密钥必须是整数,而不是字符串。问题在于api数据中的描述和ID都是字符串,而id是字母/数字组合,不能转换为整数。

我需要描述作为选择字段选项的显示文本,并且我需要将值作为ID字符串。

如果我没有整数ID,可以用作密钥吗?如果我不能使用ID字符串作为键,那么名称和值如何应用于选择字段选项?我假设键将是选择字段值。

**更新:我用数字'1'替换了项目['ID']:

items = [(1, item['Description']) for item in unit['Item']]

现在页面正在呈现,并且选择字段正在工作,但是所有选择字段的值都设置为“ 1”:

<option value="1">item name from api data</option>

该值必须是api数据中项的ID,看起来像:

'ID': 'babb87d5-323f-4d56-9ed0-e2b643a78936'

,但是不可能使用字符串作为值。任何建议将不胜感激。

1 个答案:

答案 0 :(得分:0)

我通过在字段设置中将coerce设置为int来强制设置int值。强制的默认值为unicode。一旦更改,该字段就会按预期填充。