user1429322
user1429322

Reputation: 1286

How to add confirmation dialog for POST request with Flask?

First time with Flask. I am trying to add a confirmation dialog for a form but only on certain conditions. So I am not able to do this on the client side. I was able to add it for the GET request but I wasn't able to do it for POST requests because I need to pass around the form data. Here is what I have done.

This is the form submit of the main form. On Cancel, it just refreshes the data on the current page by doing get request for config. But on Apply, it issues a POST request to /confirm route

main.html

<form class="module-form pure-form pure-form-aligned" autocomplete="off" id="uguu">
<fieldset>
   <div id="export-settings" class="module-block insight-border">
         <div class="pure-control-group">
            {{ form.export_server.label }}
            {{ form_input(form.export_server, maxlength=255) }}
         </div> 
         <div class="pure-control-group">
            {{ form.export_port.label }}
            {{ form_input(form.export_port) }}
         </div>
         <div class="submit-button-group">
            <button class="pure-button pure-button-primary" type="submit" 
                    formaction="confirm" formmethod="post">Apply</button>
            <button class="pure-button pure-button-primary cancel" type="submit"
                    formaction="config" formmethod="get">Cancel</button>
          </div>
    </div>
</fieldset>
</form>

This is the code segment in the flask server

@config_page.route("/config", methods=["GET", "POST"])
def config():
    if request.method == "POST":
         return post_config() #Uses request.form
    return get_config()


@config_page.route("/confirm", methods=["POST"])
def confirm():
    with ClassA() as class_a:
        class_a.load()
        #Need to show the confirmation only on this condition
        if class_a.is_val_x and request.form['is_val_x'] == 'on':
            #Is this the right way to go about it?
            return render_template('confirm.html', form=request.form ) 

    return redirect(url_for('.config',form=request.form),code=307) 

An finally the code segment in confirm.html. The get request works fine but I am not sure how to post the form data from the flask /confirm route to /config. I am not even sure if this is the right way to do it. Any help would be really welcome? Any solution possible in jQuery or javaScript is also welcome.

<div> Are you sure kind of dialog? </div>
<form>
   <button class="pure-button pure-button-primary deny" type="submit"  
                formaction="config" formmethod="get">Cancel</button>

   <button class="pure-button button-warning confirm" type="submit" 
                formaction="config" formmethod="post">Confirm</button>
</form>

Upvotes: 2

Views: 10240

Answers (2)

simkusr
simkusr

Reputation: 812

Well in the flask way of doing you should have separate forms.py file where you would build all your forms and use jinja2 templating.

How I would do something like that is by creating these things:

1. app/forms.py

from flask_wtf import FlaskForm
from wtforms import StringField, BooleanField, SubmitField
from wtforms.validators import DataRequired

class ConfigForm:
    conf1 = StringField('Config 1', validators=[DataRequired()])
    conf2 = StringField('Config 2', validators=[DataRequired()])
    confirm = BooleanField('Cnfirm')
    submit = SubmitField('Submit')

2. app/templates/config.py

<html>
<body>
    <h1>Config</h1>
    <p>
        {{ form.conf1.label }}<br>
        {{ form.conf1(size=(42) }}
        {% for error in form.conf1.errors %}
        <span style="color: red;">[{{ error }}]</span>
        {% endfor %}
    </p>
    <p>
        {{ form.conf2.label }}<br>
        {{ form.conf2(size=(42) }}
        {% for error in form.conf2.errors %}
        <span style="color: red;">[{{ error }}]</span>
        {% endfor %}
    </p>
    <p>{{ form.submit() }}</p>
</body>
</html>

3. app/routes.py

from flask import Flask render_template, redirect, url_for, request
from forms import ConfigForm


app = Flask(__name__)

@app.route('/config/<confirm>', methods=['GET', 'POST'])
def config(confirm):
    form = ConfigForm()
    if form.validate_on_submit():
        if form.validate_on_submit():
            db.get.value1.for.form = form.conf1.data
            db.get.value2.for.form = form.conf2.data
            if confirm:
                db.get.value3.form = form.confim.data

            db.session.commit()

            flash('You\'r changes have been saved!')
            return redirect(url_for('config'))
        elif request.method == 'GET':
            form.conf1.data = db.get.value1.for.form
            form.conf2.data = db.get.value2.for.form

    return render_template('config.html', form=form)


@app.route('/')
def index():
    confirm = True
    return redirect(url_for('config', confirm))

What I'm doing here is that I'm creating config page where data is loaded from database and in case the user wishes to update the data in the post method I will update the data to the database.

In my exaple if user enter to the /index page it redirects to cinfig page and passes the confim = True that will be updated together with post method without any user action needed.

I hope this example might atleast put you on the road to the solution you need. :)

Upvotes: 0

somsgod
somsgod

Reputation: 357

As you have said the get request works fine. So you must be seeing the template confirm.html. Edit the form tag.

<form method="POST" action="./config">
<button class="pure-button pure-button-primary deny" type="submit"  
            formaction="config" formmethod="get">Cancel</button>

<button class="pure-button button-warning confirm" type="submit" 
            formaction="config" formmethod="post">Confirm</button>
</form>

Now once you click confirm on code segment , you can by printing request data debug the form fields.

@config_page.route("/config", methods=["GET", "POST"])
def config():
if request.method == "POST":
 print(request)
 return post_config() #Uses request.form
return get_config()

If you want to submit form using ajax/jquery, you can do this.

<script type="text/javascript">
  $('.confirm').click(function (e) {
    e.preventDefault();
    $.ajax({
        url: "./config",
        type: 'post',
        dataType: "json",
        data: {
            search: request.term, request: 1
        },
        success: function (data) {
            response(data);
        }
    });
   }
</script>

Upvotes: 2

Related Questions