简体   繁体   中英

Flask WTForms SelectField Create choices from api data

I am pulling information from an api that is delivered like this:

{
  "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"
         }
       ]
     }
    ]
  }
}

I am providing a wtform with a select field:

forms.py

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

I am passing the id of the "Unit.id" to my route as a url variable:

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)

and in my view I am printing the form:

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

What I need to do is use the 'Item's, from the 'Unit' with the ID that matches the id from the url variable, as the choices for the select field.

I cannot seam to find a way to add choices to the field at the template level, which would be my preferred method. Something like:

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

I was banking on finding a solution like this, because I am most familiar with Jinja2.

Since I cannot find a way to make that work, I have been trying to figure out how to create the selectfield choices in the route. This posts was helpful: Dynamic choices WTForms Flask SelectField

however my data is structured differently because there is an extra nested layer.

I think I am getting it right, by looping through the 'Units' to find the one with an id matching my variable, and assigning that 'Unit' to a variable. Then I can do like on the post linked above, using a key value for loop (I do not know what this is called or how it works so I am not able to search for how it works):

@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)

I am pretty sure this is going to work, but I am receiving an error 'alueError: invalid literal for int() with base 10:'

obviously the key needs to be an integer, not a string. The problem is that both the description and ID from the api data are strings, and the id is a letter/number combo that can't be converted to an integer.

I need the description to be the display text for the select field option, and I need the value to be the ID string.

what can I use as the key if I don't have an integer ID? how do the name and value apply to the select field options if I can't use the ID string as the key? I am assuming the key will be the select field value.

**UPDATE: I replaced item['ID'] with the number '1':

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

and now the page is rendering, and the select field is working, but all of the select field values are set to '1':

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

The value needs to be the ID of the item form the api data, and that looks like:

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

but it doesn't seam to be possible to use a string as the value. any advice would be appreciated.

I was forcing an int value by setting coerce to int in my field settings. The default for coerce is unicode. Once I changed that the field populated as it is supposed.

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM