Business
Jobs
  • About Us
  • Solutions
    • Job Postings
      Post your job and receive qualified candidates in 48h.
    • Candidate Assessments
      500+ technical and psychological tests, plus anti-fraud.
    • Headhunting
      Tailor-made executive search from start to finish.
    • Payroll + EOR
      Payroll dispersal and EOR across 15+ LATAM countries.
  • Pricing
  • Jobs

0

315
Views
Flask-WTF form with a variable number of fields (a list of items)

I've a form to create a cocktail recipe. It has some common fields like name, description and other, and also a list of ingredients. An ingredient has an ID (foreign-key for a table of ingredients), as the value of a select tag, a name and a quantity numeric field, as user input. At first, in the HTML there is only one field for an ingredient; if the user want to add another ingredient to the recipe, a button 'Add ingredient' create another field, just after the previous one.

How can I manage this kind of form with WTForms and Flask-WTF, in a Python/Flask backend? My problem is: how can I say in the form class "there is this list that must have at least one item (an ingredient), and no maximum" so that I can properly insert the recipe into database?

about 4 years ago · Juan Pablo Isaza
1 answers
Answer question

0

maybe create a 3rd table?

Table 1 (Cocktail Table):
cocktail_id
cocktail_name

Table 2 (Ingredients Table):
cocktail_id
ingredients_name

Table 3 (Cocktail Ingredients Table):
cocktail_ingredients_id
cocktail_id
ingredients_id
quantity

Then for a given cocktail, search table 3 for all results of cocktail_id.
You can inner join the other tables to get the ingredient name or cocktail name when needed.

When uploading to database, you would just need to create a new entry for each cocktail ingredient you're saving to the cocktail ingredients table; with the cocktail_id, ingredients_id, and the quantity.

EDIT 1: There are many things you could do, for example when you are creating your form in your route, you could send to it your cocktail_id, and then when you're creating your form, you'll search for all instances of cocktail_id in your Table 3; and create a new (or set of) field(s) for each result. And the moment the user pressing 'add ingredient', you could send them

def createForm(cocktail_id):
    
    class FormClass(FlaskForm):
        # put your non dynamic fields here
        pass
    # add in your fields that are dependent on how many ingredients 

    post_variables_list = []

    # find all table 3 results for given cocktail
    table3_objects = Table3.query.filter_by(id=cocktail_id).all()
    for table3_object in table3_objects:
        setattr(FormClass, f'ingredientname_{table3_object.table3_id}', StringField('Ingredient Name', default=table3_object.ingredient_name))

        post_variables_list.append(f'ingredientname_{table3_object.table3_id}')

    return FormClass(), post_variables_list


@app.route('/example_route/<int:cocktail_id>')
def example_route(cocktail_id):

     form, post_variables_list = createForm(cocktail_id)
     if request.method=='POST':
        submit_dictionary = {}
        submit_dictionary = form.data

        for current_variable in post_variables_list:
            fieldname, table3_id = current_variable.split('_')
        
            # find existing object, that you can create by redirecting to a different route 
            # which just creates a new table 3 entry, which is associated w/ this cocktail each time you
            # press add ingredient and then redirects you to here
            table3_object = db.session.query(Table3).filter(Table3.id==table3_id).first()
            if fieldname = 'name':
                table3_object.name = submit_dictionary[current_variable]
            # could have other conditions here for other fields

            db.session.add(table3_object)
            db.session.commit()
            

# route which just creates a new empty ingredient
@app.route('create_new_empty_ingredient/int:cocktail_id')
def create_new_empty_ingredient(cocktail_id):

    # create new entry in table 3
    table3_object = Table3 (
        cocktail_id = cocktail_id
    )
    db.session.add(table3_object)
    db.session.commit()

    # redirect back to example_route
    return redirect(url_for('example_route', cocktail_id=cocktail_id))
about 4 years ago · Juan Pablo Isaza Report
Answer question
Find remote jobs

Discover the new way to find a job!

Top jobs
Top job categories
Business
Post vacancy Pricing Sales
Legal
Terms and conditions Privacy policy
© 2026 PeakU Inc. All Rights Reserved.
Andres GPT
Show me some job opportunities
There's an error!