【问题标题】:Parsing Python Script using AJAX request and showing data on same page in Flask使用 AJAX 请求解析 Python 脚本并在 Flask 的同一页面上显示数据
【发布时间】:2019-12-10 08:01:13
【问题描述】:

我正在尝试使用 AJAX 请求处理 Python 脚本。我在 Flask 上渲染我的网页。当我不使用 Flask 时,我的解决方案在我的本地计算机上运行,​​但自从我移植到 Flask 以在 Azure 上部署后,我开始遇到问题。

我的目标是将 home.html 页面上的表单中的“country”和“rate”传递给“script.py”文件。 “script.py”利用这些变量并打印出一个静态 HTML 响应,然后应该在我的 HTML 页面的“result”div 标签中进行更新。

这是我的 Flask application.py 文件:

from flask import Flask, render_template, request

app = Flask(__name__)

@app.route("/", methods=['GET', 'POST'])
def home():
    return render_template('home.html')

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

我的 AJAX 请求:

function python_process() {

    var rate = $('input[name=rate]').val();
    var country = $('select[name=country]').val();

    $.ajax({

        url: "/static/script.py",
        type: "POST",
        data: {
            "rate" : rate, 
            "country": country
            },

        success: function(data){
                    var result = $('<div>').append(data);
                    $('#result').html(result);
                },
        error:  function(){
                    console.log('in error');
                }
        });
};

我尝试过的事情:

  1. 试图让我的 script.py 文件成为它自己的 Flask 方法,但是脚本太大并且在我尝试时总是给我一个服务器错误。
  2. 尝试在 AJAX 成功调用中控制台打印“数据”变量,但默认控制台日志始终显示“错误”。

【问题讨论】:

  • 你不能这样做。 Url /static/script.py 指向烧瓶,烧瓶尝试将其内容作为普通文件(即图像、.css 等)发送。它不会执行它。您必须向烧瓶中的某些功能发送请求,并且烧瓶必须执行它。并且烧瓶必须像任何其他模板一样将其结果提供给客户端。
  • 您可以尝试使用模块subprocess 在烧瓶中运行script.py 并捕获输出。
  • @furas 在这种情况下我会在哪里调用子流程?而且这也不允许我将任何变量从我的 HTML 表单传递给 script.py
  • 你必须在 Flask 中使用 ie 创建函数。 @app.route('/scipt') 并在此函数内部运行 subprocess。 AJAX 将运行 url /script。这是普通的烧瓶函数,因此它可以从 AJAX 获取参数。而subprocess 可以运行"script.py arg1 arg2 arg3"

标签: python ajax flask


【解决方案1】:

您可以使用subprocess 在烧瓶中运行脚本并捕获输出。

import subprocess

@app.route("/script", methods=['GET', 'POST'])
def home():
    rate = request.form.get('rate', '')
    country = request.form.get('country', '')

    output = subprocess.check_output('python script.py {} {}'.format(rate, country), shell=True)

    return output

而 AJAX 必须使用 url /script


最小的工作示例。

main.py(flask + template 在一个文件中)

#!/usr/bin/env python3 

from flask import Flask, render_template, request, render_template_string
import subprocess

app = Flask(__name__)

@app.route("/", methods=['GET', 'POST'])
def home():
    return render_template_string('''<!DOCTYPE html>
<html>
<head>
<!-- can't be `slim` version because it has not `$.ajax` -->
<script src="https://code.jquery.com/jquery-3.4.1.min.js"></script>
</head>
<body>

<form>
Rate: <input type="text" name="rate"/><br/>
Country: <select name="country"/><option>France</option><option>Germany</option></select><br/>
<button>OK</button>
</form>

<div id="result"></div>

<script>$(function() {
    $('button').click(function(e) {

        var rate = $('input[name=rate]').val();
        var country = $('select[name=country]').val();

        // alert('rate: "' + rate + '" | country: "' + country + '"');

        $.post({
            url: "/script",
            data: {
                "rate" : rate, 
                "country": country
            },
            success: function(data){
                var result = $('<div>').append(data);
                $('#result').html(result);
            },
            error: function(){
                console.log('in error');
            }
        });

        e.preventDefault();
    });
});    
</script>
</body>
</html>''')

@app.route("/script", methods=['GET', 'POST'])
def script():
    rate = request.form.get('rate')
    country = request.form.get('country')

    print('[form] rate: "{}" | country: "{}"'.format(rate, country))

    # I use `""` to send empty string as argument
    output = subprocess.check_output('python3 script.py "{}" "{}"'.format(rate, country), shell=True)

    return output

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

脚本.py

#!/usr/bin/env python3 

import sys

rate = '?'
country = '?'

# send on screen instead of sending to flask
sys.stderr.write( '[sys.argv] {}\n'.format(str(sys.argv)) )

if len(sys.argv) > 1:
    rate = sys.argv[1]

if len(sys.argv) > 2:
    country = sys.argv[2]

print('[script.py] rate: "{}" | country: "{}"'.format(rate, country))

【讨论】:

  • 试过了,谢谢,但控制台显示以下错误 - POST http:///script 500 (INTERNAL SERVER ERROR)
  • 对不起,应该是check_output 而不是call_output。和request.form 而不是request.post。如果脚本未设置为可执行文件,那么您可能需要在 check_output 中使用python script.py。顺便说一句:如果您在控制台/终端/cmd.exe 中运行,那么它应该会向您显示有关问题的更多信息。
  • 我添加了我用来测试它的最小工作示例。
  • 已经对此进行了测试,但问题似乎在于表单请求变量转移到脚本中。我得到输出 - “[script.py] rate: “None” | country: “None””,表明这些请求表单获取变量没有被正确分配。我之前的脚本使用的是 CGI 模块,我在脚本中用你的 sys 模块替换了这些模块
  • 如果你得到None,那么它以script.py None None 执行,这意味着它无法从request.form 获取值 - 顺便说一句:我已经提到它 - 在第一个版本中我有@987654336 @ 但必须是 request.form
猜你喜欢
  • 1970-01-01
  • 2017-10-12
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2022-01-01
  • 2014-11-09
相关资源
最近更新 更多