简体   繁体   中英

flask wtforms, what input is pressed

Flask beginner here, bear with me please !

In this little piece of code I simplified for the question, I have for a defined route / with 2 forms : I'd like the add form to add things to the db and the delete form to delete things, simple.

However my issue is that in this code I can't differentiate which input button from the form is pressed as formadd.validate() and formdel.validate() both always return true.

How can I differentiate which submit button is pressed in order to manipulate the database accordingly ?

At first I wrote what is currently commented below, but obviously it doesn't work since the validate method returns true....

from flask import Flask, render_template, request
from flask.ext.sqlalchemy import SQLAlchemy
from wtforms import Form, StringField


app = Flask(__name__)
app.config['SQLALCHEMY_DATABASE_URI'] = 'sqlite:///botdb.db'
db = SQLAlchemy(app)

class BotFormAdd(Form):
    botname = StringField('bot name')
    botdescription = StringField('bot description')


class BotFormDelete(Form):
    botid = StringField('bot id')


@app.route('/', methods=['GET', 'POST'])
def index():
    formadd = BotFormAdd(request.form)
    formdel = BotFormDelete(request.form)
    if request.method == 'POST':
        print(formadd.validate(), formdel.validate())
    # if request.method == 'POST' and formadd.validate():
    #     print('in formadd')
    #     bot = Bot(name=formadd.botname.data, description=formadd.botdescription.data)
    #     db.session.add(bot)
    #     db.session.commit()
    #     return redirect(url_for('index'))
    # if request.method == 'POST' and formdel.validate():
    #     print('in formdel')
    #     db.session.delete(formdel.botid.data)
    #     db.session.commit()
    #     return redirect(url_for('index'))
    return render_template('index.html', title='Home', formadd=formadd, formdel=formdel)


if __name__ == '__main__':
    app.run(debug=True)

<!DOCTYPE html>
<html>
<head lang="en">
    <meta charset="UTF-8">
    <title>this is a test</title>

</head>
<body>
<form method=post action="/">
  <dl>
    {{ formadd.botname }}
    {{ formadd.botdescription }}
  </dl>
  <p><input type=submit name='add' value='add this'>
</form>
<form method=post action="/">
  <dl>
    {{ formdel.botid }}
  </dl>
  <p><input type=submit name='delete' value='delete this'>
</form>
</body>
</html>

There's lots of ways of doing this, but it breaks down into two categories-- either you indicate it via the route, or via an element on a form.

Most people would just add separate routes:

@app.route('/delete-bot/', methods=['post'])
def delete_bot():
    form = BotFormDelete()
    if form.validate():
        delete_bot(id=form.botid.data)
    flash('Bot is GONE')
    return redirect(url_for('index'))

So your delete form would submit to that route, get processed and sent back to index.

<form method='post' action='url_for('delete_bot')>

And you'd have a different route for adding a bot.

Alternatively you could check what type of form it was from it's contents. Eg

if request.form.get('botid'):
    # it has a botid field, it must be a deletion request
    form = BotFormDelete()
    form.validate()
    delete_bot(form.botid.data)
else:
    form = BotFormAdd()
    ....

But that way seems like it would get messy quickly.

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