如何在不刷新页面的情况下使用 Flask 写入 HTML 页面?

How to write to an HTML page using Flask without refreshing the page?

我正在重新创建简单的 Web 应用程序来练习。在这个网站Password Generator,一旦你按下生成密码,生成的密码就会被输入到文本框中。我如何在 Flask 中执行此操作?我所做的解决方案是重定向到一个仅包含密码的新网页,但我认为这不是一个好的设计。

@app.route("/", methods=["GET", "POST"])
def index():
if request.method == "GET":
    return render_template("index.html")
else:
    # Get the input values
    length = int(request.form.get("charnum"))
    numbers = bool(request.form.get("numbers"))
    symbols = bool(request.form.get("symbols"))
    lowercase = bool(request.form.get("lowercase"))
    uppercase = bool(request.form.get("uppercase"))
    similar = bool(request.form.get("excludeSimilar"))
    ambiguous = bool(request.form.get("ambiguous"))

    # Generate Password with the preceding conditions
    password = generate_pass(length, symbols, numbers, uppercase, lowercase, similar, ambiguous)
    return render_template("index.html", password=password)

对于网页中的 real-time 响应,您必须使用 javascript。你可以用 javascript 调用你的 flask API (使用像 AJAX,... ), 然后将生成的密码放在文本框中或在 javascript.

中实现你的密码生成算法

需要使用JavaScript向服务器发送AJAX请求。服务器可以 return 只有密码(没有 HTML)并且 JavaScript 必须把它放在文本框中。

但是您 link 的页面使用 JavaScript 直接在浏览器中生成密码


使用 JavaScript 从 FORM 获取值,发送到服务器,从服务器获取结果并将密码放入 FORM 的最小工作代码。

from flask import Flask, request, render_template_string
import random
import string

app = Flask(__name__)

@app.route('/', methods=['GET', 'POST'])
def index():
    if request.method == "POST":
        data = request.json

        lower_number = int(data.get('lower', 0))
        upper_number = int(data.get('upper', 0))

        password_lower = random.choices(string.ascii_lowercase, k=lower_number)
        password_upper = random.choices(string.ascii_uppercase, k=upper_number)

        password = password_lower + password_upper
        random.shuffle(password)  # change order of chars  (work in-place so doesn't need to assign to variable)

        return "".join(password)

    return render_template_string('''<!DOCTYPE html>
<html>
<head>
    <meta charset="utf-8">
</head>
<body>
<form method="POST">
    Lower: <input type="text" id="lower_id" value="10" /><br/>
    Upper: <input type="text" id="upper_id" value="10" /><br/>
    <button type="submit" name="btn" onclick="generate();return false">GENERATE</button></br>
    <input type="text" id="password_id" /><br/>
</form>
<script>
var password = document.getElementById("password_id");
var lower_input = document.getElementById("lower_id");
var upper_input = document.getElementById("upper_id");

function generate() {
    fetch("/", {
        method: "POST",
        body: JSON.stringify({
            lower: lower_input.value,
            upper: upper_input.value,
        }),
        headers: {
          'Accept': 'application/json',
          'Content-Type': 'application/json'
        },        
    })
    .then(response => response.text())
    .then(text => {password.value = text;})
}
</script>
</body>
</html>''')


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

编辑:

fetch我设置

  • url "/",
  • 方法POST,
  • 数据转换为JSON,
  • content-type as JSON - 所以 Flask 可以用 request.json,
  • 得到它
  • accept as JSON - 通知 Flask 我希望响应为 JSON(但我不尊重它,在 Flask 中我发送普通文本而不是 JSON - 所以我可以跳过这个 header)

因为JavaScript使用异步函数所以 fetch 使用 .then() 在获得服务器响应时执行下一个函数。此函数从响应中获取 text/body。它还必须等待结果,并在最终从响应中获取文本时使用 .then() 执行下一个函数。并且此函数将此文本放入 <input> 作为密码。

Mozilla:Using Fetch and Fetch API