Make a client POST request to Flask render_template endpoint

问题: After long searching on here and on the web I could not find what I require. Here is a distilled minimum verifiable example of my issue. To set the background for the pro...

问题:

After long searching on here and on the web I could not find what I require. Here is a distilled minimum verifiable example of my issue.

To set the background for the problem, here is the actual use case that I intend to implement. There is a heatmap on endpoint /heatmap, users can click on the cells and they should be redirected to a different endpoint /more-info-on-cell. Depending on the cell clicked, the user will get different results. I almost get the intended result. The only issue is that the page is not really properly rendered because the javascript of /more-info-on-cell does not get executed for some reason.

Here is the folder structure that you require for this example:

root
|-templates
|  -index.html
|  -page.html
|-index.py

And here are the files: index.html

  <!DOCTYPE html>
  <html>
  <head> 
  <title>Title of the document</title> 
  </head>

  <body>
      <a id="clickMe" style="cursor: pointer">Click here to send POST to render template on the backend</a>
  </body>

  <script 
    src="https://code.jquery.com/jquery-3.4.1.min.js" 
    integrity="sha256-CSXorXvZcTkaix6Yvo6HppcZGetbYMGWSFlBw8HfCJo=" 
    crossorigin="anonymous"></script>
  <script>
      $(document).ready(function() {
          $("#clickMe").on('click', function() {
              console.log('clicked, making a request')

              $.ajax({
                  type: 'POST',
                  url: '/',
                  data: JSON.stringify({}),
                  contentType: 'application/json',
                  success: function(response) { window.document.write(response);  }
              })
          })
      })
  </script>

  </html>

page.html

 <!DOCTYPE html>
 <html>
 <head>
 <title>Title of the document</title>
 </head>

 <body>
 The content of the document......
 </body>

 <script
   src="https://code.jquery.com/jquery-3.4.1.min.js"
   integrity="sha256-CSXorXvZcTkaix6Yvo6HppcZGetbYMGWSFlBw8HfCJo="
   crossorigin="anonymous"></script>
     <script>
         $(document).ready(function() {
             alert('the doc is ready');
         })
     </script>

 </html>

index.py

 #!/usr/bin/env python3
 from flask import Flask, request, render_template, jsonify
 app = Flask(__name__)

 @app.route("/", methods=["GET", "POST"])
 def index():
     if request.method == "GET":
         return render_template('index.html')
     elif request.method == "POST":
         return render_template('page.html')

You can verify that if you click on the link in index.html you are successfully redirected to page.html but its javascript is never executed. And so you never get the alert that we have defined in page.html.

The problem should be solved by completely working with the flask backend here, since the templates in my actual use case have jinja variables in them too. Everything works perfectly if you make a request through a form with method having the correct url and action being POST. Although, as soon as I start making javascript client POST requests, it sort of works in that I get to the right page, but it is rendered incorrectly + javascript on document ready never gets executed.


回答1:

For anyone who has such a use case too, ensure that you use a method post like below (put it inside the index.html in this case):

  <script>
      $(document).ready(function() {
          $("#clickMe").on('click', function() {
              console.log('clicked, making a request')

             post('/', {'key-1': 'val-1'});
          })
      })

 function post(path, params, method='post') {
     const form = document.createElement('form');
     form.method = method;
     form.action = path;

     for (const key in params) {
         if (params.hasOwnProperty(key)) {
             const hiddenField = document.createElement('input');
             hiddenField.type = 'hidden';
             hiddenField.name = key;
             hiddenField.value = params[key];

             form.appendChild(hiddenField);
         }
     }

     document.body.appendChild(form);
     form.submit();
 }
  </script>

This creates a hidden form on the web page and then submits the form, from then onwards, flask processes everything properly.

  • 发表于 2019-07-07 04:52
  • 阅读 ( 154 )
  • 分类:sof

条评论

请先 登录 后评论
不写代码的码农
小编

篇文章

作家榜 »

  1. 小编 文章
返回顶部
部分文章转自于网络,若有侵权请联系我们删除