简体   繁体   English

如何使用 AJAX 将表单正确提交到 Flask?

[英]How to properly submit form to Flask with AJAX?

I'm a beginner in Python and AJAX, why when I run my app.py with app.html, the result that I want to display are replaced with a whole form?我是 Python 和 AJAX 的初学者,为什么当我用 app.html 运行我的 app.py 时,我想显示的结果被整个表单替换了?

Here is my code:这是我的代码:

from flask import Flask, render_template, request

app = Flask(__name__, 
template_folder='C:\\Users\\iyzadsyammil\\PycharmProjects\\PVT - Copy')

@app.route('/App',methods=['GET', 'POST'])
def showapp():
error = " "
finalpb= 0
x=0
logpb=0

if request.method == 'POST':
    ingor = request.form['inGOR']

    ingor = float(ingor)

    try:
        finalpb = ingor
    except ValueError:
        error = "Please enter an appropriate value!"

return render_template('app.html',error=error,finalpb=finalpb)

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

This is my Python Flask file这是我的 Python Flask 文件

<!DOCTYPE html>
<html lang="en">
  <head>
    <meta charset="utf-8">
    <meta http-equiv="X-UA-Compatible" content="IE=edge">
    <meta name="viewport" content="width=device-width, initial-scale=1">
    <!-- The above 3 meta tags *must* come first in the head; any other head content must come *after* these tags -->
    <meta name="description" content="">
    <meta name="author" content="">
    <link rel="icon" href="https://media.licdn.com/mpr/mpr/shrink_200_200/AAEAAQAAAAAAAAfJAAAAJDIxMDc1NWExLTczODgtNDBhOS1iZmYwLWRmOTZjZjc2NzVhYQ.png">

    <title>Invigour Tool</title>

    <!-- Bootstrap core CSS -->
    <link href="http://getbootstrap.com/dist/css/bootstrap.min.css" rel="stylesheet">
    <!-- Custom styles for this template -->
    <!--<link href="dashboard.css" rel="stylesheet" type="text/css">-->
    <style>

/* Move down content because we have a fixed navbar that is 50px tall */
body {
  padding-top: 50px;

}

/*
 * Global add-ons
 */

.sub-header {
  padding-bottom: 10px;
  border-bottom: 1px solid #eee;
}

/*
 * Top navigation
 * Hide default border to remove 1px line.
 */
.navbar-fixed-top {
  border: 0;
}

/*
 * Sidebar
 */

/* Hide for mobile, show later */
.sidebar {
  display: none;
}
@media (min-width: 768px) {
  .sidebar {
    position: fixed;
    top: 51px;
    bottom: 0;
    left: 0;
    z-index: 1000;
    display: block;
    padding: 20px;
    overflow-x: hidden;
    overflow-y: auto; /* Scrollable contents if viewport is shorter than content. */
    background-color: #f5f5f5;
    border-right: 1px solid #eee;
  }
}

/* Sidebar navigation */
.nav-sidebar {
  margin-right: -21px; /* 20px padding + 1px border */
  margin-bottom: 20px;
  margin-left: -20px;
}
.nav-sidebar > li > a {
  padding-right: 20px;
  padding-left: 20px;
}
.nav-sidebar > .active > a,
.nav-sidebar > .active > a:hover,
.nav-sidebar > .active > a:focus {
  color: #fff;
  background-color: #428bca;
}

/*
 * Main content
 */

.main {
  padding: 20px;
}
@media (min-width: 768px) {
  .main {
    padding-right: 40px;
    padding-left: 40px;
  }
}
.main .page-header {
  margin-top: 0;
}

/*
 * Placeholder dashboard ideas
 */

.placeholders {
  margin-bottom: 30px;
  text-align: center;
}
.placeholders h4 {
  margin-bottom: 0;
}
.placeholder {
  margin-bottom: 20px;
}
.placeholder img {
  display: inline-block;
  border-radius: 50%;
}

/* Custom page footer */
.footer {
  padding-top: 10px;
  margin-top: 2cm;
  color: #777;
  border-top: 1px solid #e5e5e5;

}

.cal{
    float: right;
    box-shadow: 0 12px 16px 0 rgba(0,0,0,0.24), 0 17px 50px 0 rgba(0,0,0,0.19);
    width: 180px;
    height: 85px;
    font-size: 30px;
    border-radius: 24px;
    background-color: limegreen;
    position: relative;
    right: 0.5cm;
}

.conti{
    float: right;
    box-shadow: 0 12px 16px 0 rgba(0,0,0,0.24), 0 17px 50px 0 rgba(0,0,0,0.19);
    width: 180px;
    height: 85px;
    font-size: 30px;
    border-radius: 24px;
    background-color: limegreen;
}

.rest{
    float: right;
    box-shadow: 0 12px 16px 0 rgba(0,0,0,0.24), 0 17px 50px 0 rgba(0,0,0,0.19);
    width: 180px;
    height: 85px;
    font-size: 30px;
    border-radius: 24px;
    background-color: limegreen;
    margin-top: 3cm;
    position: relative;
    left: 7cm;
}

input[type="number"]{
    margin-left: 3cm;
}

select[id=cor4],[id=cor5]{
    width: 165px;
}

select{
    margin-left: 1cm;
}

p[id=pb],[id=rs],[id=bo],[id=co],[id=uo],[id=po],[id=zf],[id=bg],[id=pg],[id=ug],[id=bw],[id=uw],[id=pw],[id=cw],[id=iow],[id=iog]{
    margin-left: 4cm;
}

tr:hover{
    background-color:#f5f5f5}

    </style>
  </head>

<body>
  <div>

    <nav class="navbar navbar-inverse navbar-fixed-top">
      <div class="container-fluid">
        <div class="navbar-header">
          <button type="button" class="navbar-toggle collapsed" data-toggle="collapse" data-target="#navbar" aria-expanded="false" aria-controls="navbar">
            <span class="sr-only">Toggle navigation</span>
            <span class="icon-bar"></span>
            <span class="icon-bar"></span>
            <span class="icon-bar"></span>
          </button>
          <a class="navbar-brand" href="http://www.invigourenergy.com/">Invigour Energy</a>
        </div>
        <div id="navbar" class="navbar-collapse collapse">
          <ul class="nav navbar-nav navbar-right">
            <li><a href="Menu">Dashboard</a></li>
            <li><a href="PVT Menu">PVT Tool</a></li>
            <li><a href="#">Help</a></li>
          </ul>
          <form class="navbar-form navbar-right">
            <input type="text" class="form-control" placeholder="Search...">
          </form>
        </div>
      </div>
    </nav>

    <div class="container-fluid">
      <div class="row">
        <div class="col-sm-3 col-md-2 sidebar">
          <ul class="nav nav-sidebar">
            <li class="active"><a href="#">Overview <span class="sr-only">(current)</span></a></li>

            <li><a href="#"> </a></li>
            <li><a href="#"> </a></li>
          </ul>
          <ul class="nav nav-sidebar">
            <li><a href=""> </a></li>
            <li><a href=""> </a></li>
            <li><a href=""> </a></li>
            <li><a href=""> </a></li>
            <li><a href=""> </a></li>
          </ul>
        </div>
        <div class="col-sm-9 col-sm-offset-3 col-md-10 col-md-offset-2 main">
          <form method="POST" class="form" id="fm">
                <h3>Basic PVT Application</h3>
                <br>
                <table>
                    <tr><td><u>Input Data</u></td><td></td><td></td></tr>
                    <tr><td>&nbsp</td></tr>
                    <tr><td>Solution GOR(Rs) </td><td><input type="number" step="any" id="inGOR" name="inGOR"></td><td>scf/bbl</td></tr>
                    <tr><td>Oil Gravity </td><td><input type="number" step="any" id="inOG"></td><td>API</td></tr>
                    <tr><td>Gas Specific Gravity </td><td><input type="number" step="any" id="inGG"></td><td>SG(air=1)</td></tr>
                    <tr><td>Temperature </td><td><input type="number" step="any" id="inT"></td><td>◦F</td></tr>
                    <tr><td>Pressure </td><td><input type="number" step="any" id="inP"></td><td>Psia</td></tr>

                    <tr><td>Mole Percent H2S </td><td><input type="number" step="any" id="inH2S"></td><td>%mole</td></tr>
                    <tr><td>Mole Percent CO2 </td><td><input type="number" step="any" id="inCO2"></td><td>%mole</td></tr>
                    <tr><td>Mole Percent N2 </td><td><input type="number" step="any" id="inN2"></td><td>%mole</td></tr>
                    <tr><td>Water Salinity </td><td><input type="number" step="any" id="inWS"></td><td>ppm</td></tr>
                </table>
                <br>
                <table>
                    <tr><td><u>Correlation</u></td><td></td></tr>
                    <tr><td>&nbsp</td></tr>
                    <tr>
                        <td>Bubble Point Pressure(Pb) </td>
                        <td>
                            <select id="cor1">
                                <option value="none"></option>
                                <option value="VB">Vasquez and beggs</option>
                                <option value="AM">Al-Marhoun</option>
                                <option value="G">Glaso</option>
                                <option value="PF">Petrosky and Farshad</option>
                                <option value="S">Standing</option>
                            </select>
                        </td>
                    </tr>
                    <tr>
                        <td>Solution GOR(Rs)</td>
                        <td>
                            <select id="cor2">
                                <option value=" "></option>
                                <option value="VB">Vasquez and beggs</option>
                                <option value="AM">Al-Marhoun</option>
                                <option value="G">Glaso</option>
                                <option value="PF">Petrosky and Farshad</option>
                                <option value="S">Standing</option>
                            </select>
                        </td>
                    </tr>
                    <tr>
                        <td>Oil Formation Volume Factor(Bo)  </td>
                        <td>
                            <select id="cor3">
                                <option value=" "></option>
                                <option value="VB">Vasquez and beggs</option>
                                <option value="AM">Al-Marhoun</option>
                                <option value="G">Glaso</option>
                                <option value="PF">Petrosky and Farshad</option>
                                <option value="S">Standing</option>
                            </select>
                        </td>
                    </tr>
                    <tr>
                        <td>Oil Viscosity(µo) </td>
                        <td>
                            <select id="cor4" size="">
                                <option value=" "></option>
                                <option value="CC">Chew Connally</option>
                                <option value="BR">Beggs Robinson</option>
                            </select>
                        </td>
                    </tr>
                    <tr>
                        <td>Water Viscosity(µw) </td>
                        <td>
                            <select id="cor5" size="">
                                <option value=" "></option>
                                <option value="Mc">Mccain</option>
                                <option value="BB">Brill and Beggs</option>
                            </select>
                        </td>
                    </tr>
                </table>
                <br>
                <button type="button" class="conti" onclick="location.href='Out';" >Continue</button><button type="submit" id="cb" class="cal">Calculate</button>
                <button type="button" class="rest" onclick="res()">Reset</button>
                <br>

                <table class="rlt">
                    <tr><td><u>Result</u></td><td></td></tr>

                    <tr><td>Pb</td><td><p id="pb">{{finalpb}}</p></td></tr>
                    <tr><td>Rs(Solution GOR)</td><td><p id="rs"></p></td></tr>
                    <tr><td>Bo</td><td><p id="bo"></p></td></tr>
                    <tr><td>Co</td><td><p id="co"></p></td></tr>
                    <tr><td>µo</td><td><p id="uo"></p></td></tr>
                    <tr><td>ρo</td><td><p id="po"></p></td></tr>
                    <tr><td>Z Factor</td><td><p id="zf"></p></td></tr>
                    <tr><td>Bg</td><td><p id="bg"></p></td></tr>
                    <tr><td>ρg</td><td><p id="pg"></p></td></tr>
                    <tr><td>µg</td><td><p id="ug"></p></td></tr>
                    <tr><td>Bw</td><td><p id="bw"></p></td></tr>
                    <tr><td>µw</td><td><p id="uw"></p></td></tr>
                    <tr><td>ρw</td><td><p id="pw"></p></td></tr>
                    <tr><td>Cw</td><td><p id="cw"></p></td></tr>
                    <tr><td>IFT oil-water</td><td><p id="iow"></p></td></tr>
                    <tr><td>IFT oil-gas</td><td><p id="iog"></p></td></tr>
                </table>
                <script src="https://ajax.googleapis.com/ajax/libs/jquery/3.2.1/jquery.min.js"></script>
                <script>

               $('#fm').on('submit',function (e) {
                      $.ajax({
                          type: 'post',
                          url: '/App',
                          data: $('#fm').serialize(),
                          success: function (q) {
                       document.getElementById("pb").innerHTML= q;
                         }
                       });
                     e.preventDefault();
                   });


                </script>

                <br/>
                <footer class="footer">
                <p>Copyright © Invigour Energy 2016</p>
                </footer>
            </form>

        </div>

        </div>
      </div>
  </div>


    <!-- Bootstrap core JavaScript
    ================================================== -->
    <!-- Placed at the end of the document so the pages load faster -->
    <script src="https://ajax.googleapis.com/ajax/libs/jquery/1.12.4/jquery.min.js"></script>
    <script>window.jQuery || document.write('<script src="../../assets/js/vendor/jquery.min.js"><\/script>')</script>
    <script src="http://getbootstrap.com/dist/js/bootstrap.min.js"></script>
    <!-- Just to make our placeholder images work. Don't actually copy the next line! -->
    <script src="http://getbootstrap.com/assets/js/vendor/holder.min.js"></script>
    <!-- IE10 viewport hack for Surface/desktop Windows 8 bug -->
    <script src="http://getbootstrap.com/assets/js/ie10-viewport-bug-workaround.js"></script>
</body>
</html>

This is my html这是我的 html

Please have a look at my ajax part only请只看我的ajax部分

Updated response:更新回复:

Let me rephrase my original answer: Don't use AJAX.让我重新表述我原来的答案:不要使用 AJAX。 it is completely unnecessary.这是完全没有必要的。 Delete all of your script items.删除所有脚本项。 I just took your code and made it work on my local flask environment nicely without any AJAX.我只是拿了你的代码,让它在我本地的 Flask 环境中很好地工作,没有任何 AJAX。 Here is what you need to do:以下是您需要做的:

1) Update your 'buttons' so that they are inputs, type=submit and give them the value of the name of the button you desire (eg Calculate). 1) 更新您的“按钮”,使它们成为输入,type=submit 并为它们提供您想要的按钮名称的值(例如计算)。

2) Your form inputs do not have a 'name' attribute. 2)您的表单输入没有“名称”属性。 Without that, the form has no key/value association.没有它,表单就没有键/值关联。 For example, look at your inOG input.例如,查看您的 inOG 输入。 You need to give it a name...something like name="inOG" .你需要给它起一个名字……类似于name="inOG"

3) I don't know why you have your C drive as a configuration item. 3)我不知道你为什么把你的C盘作为配置项。 Maybe it's a Windows thing?也许这是Windows的事情?

Now when you debug, you should see the form values come in nicely.现在,当您调试时,您应该会看到表单值很好地输入。


You are running into problems for a few reasons:您遇到问题有以下几个原因:

1) Your form is far too busy. 1) 你的表格太忙了。 Ideally, in my experience, the form should really only contain the necessary inputs and labels.理想情况下,根据我的经验,表单应该只包含必要的输入和标签。 Also, it is generally not wise to format an html page using tables.此外,使用表格格式化 html 页面通常是不明智的。 You might consider using Flask-WTF if you don't feel like coding out a form in it's entirety.如果您不想完整地编写表单,您可以考虑使用Flask-WTF One of the nice things of Flask is the ability to use templates like WTF. Flask 的优点之一是能够使用像 WTF 这样的模板。

2) If you set up the form nicely, then you won't even need to use AJAX, which might be preferable in your case. 2)如果您很好地设置了表单,那么您甚至不需要使用 AJAX,这在您的情况下可能更可取。 The once the form is submitted, your Flask code should do the rest.提交表单后,您的 Flask 代码应该完成剩下的工作。

2) If you are bent on using AJAX it's worth noting that your AJAX post is right in the middle of your form code. 2) 如果您一心想使用 AJAX,值得注意的是您的 AJAX 帖子就在表单代码的中间。 Since your browser reads code sequentially, it is picking up an AJAX post before the form has finished rendering.由于您的浏览器按顺序读取代码,因此它会在表单完成渲染之前获取 AJAX 帖子。 You should insert your <script> tag either at the top of the body or at the bottom of it.您应该在正文的顶部或底部插入<script>标签。

3) You are using JQuery, which means you need to wrap any executable code in a $(document).ready function. 3) 您正在使用 JQuery,这意味着您需要将任何可执行代码包装在$(document).ready函数中。 So, once you have moved your script as mentioned above, you should write is as follows:所以,一旦你按照上面提到的方式移动了你的脚本,你应该写如下:

<script>

$(document).ready(function(){

$('#fm').on('submit',function (e) {
     $.ajax({
      type: 'post',
      url: '/App',
      data: $('#fm').serialize(),
       success: function (q) {
       document.getElementById("pb").innerHTML= q;
       }
      });
     e.preventDefault();
     });

}

In summary, I would suggest cleaning up your form and doing away with AJAX altogether.总之,我建议清理您的表单并完全取消 AJAX。 Looking at your form data, it doesn't seem like there is anything special that would require a break away from normal form submission.查看您的表单数据,似乎没有什么特别的需要脱离正常的表单提交。

Good Luck!祝你好运!

So after dealing with my own issues in Flask and AJAX, I wouldn't say don't use AJAX.所以在处理了我自己在 Flask 和 AJAX 中的问题之后,我不会说不要使用 AJAX。 As an example, I had a form that needed to be submitted and it took long enough to generate a 504. Sometimes AJAX is necessary.举个例子,我有一个需要提交的表单,它花费了足够长的时间来生成 504。有时 AJAX 是必要的。

In the off-case where it is necessary and you happen to be using Flask (and/or FLASK-WTF) you first need to update your form element to use the new event.在必要的情况下并且您碰巧正在使用 Flask(和/或 FLASK-WTF),您首先需要更新表单元素以使用新事件。 This can be done with the following addition.这可以通过以下添加来完成。

{{ form.my_element(**{"onchange":"my_ajax_function()"}) }}

The dictionary is passed back as a kwarg to Flask forms and sets the onchange event to use my_ajax_function() (just replace this with "onclick" if it's a button)字典作为 kwarg 传递回 Flask 表单并将onchange事件设置为使用my_ajax_function() (如果它是一个按钮,只需将其替换为“onclick”)

Next update your javascript with the new function.接下来用新函数更新你的 javascript。 This function should do the following:此函数应执行以下操作:

  1. Get any fields required to perform this work获取执行此工作所需的任何字段
  2. Start the ajax request and include the url (route), the data to be sent (if any), and what action to perform on a successful/failed request.启动 ajax 请求并包含 url(路由)、要发送的数据(如果有)以及对成功/失败请求执行的操作。

This will update any fields as required and keep data in existing fields.这将根据需要更新任何字段并将数据保留在现有字段中。 I will say that it is much easier on life if you avoid AJAX and let Flask do it's thing, but sometimes this is unavoidable.我会说,如果您避免使用 AJAX 而让 Flask 来做这件事,生活会容易得多,但有时这是不可避免的。

I haven't tried just returning without a response instead of using render_template, redirect, or make_response from a post request to see if the fields remain as they were, but it's definitely something to experiment with.我还没有尝试过在没有响应的情况下返回,而不是使用 post 请求中的 render_template、redirect 或 make_response 来查看字段是否保持原样,但这绝对是值得尝试的。

I've only used AJAX for creating dynamic SelectFields, but there are some promising articles on form submissions, just looks like FlaskForms doesn't know how to convert this type of request back to the Form object since they are sent as query parameters, so you'll need to manually validate the fields after they have returned.我只使用 AJAX 来创建动态 SelectFields,但有一些关于表单提交的有前途的文章,看起来 FlaskForms 不知道如何将这种类型的请求转换回 Form 对象,因为它们是作为查询参数发送的,所以您需要在字段返回后手动验证它们。 How to submit a Flask-WTF form with Ajax 如何使用 Ajax 提交 Flask-WTF 表单

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

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