发布/获取请求不起作用(AJAX、Flask)

Post/Get request not working (AJAX, Flask)

提问人:JBatswani 提问时间:8/2/2023 最后编辑:Abdulrahman HasanatoJBatswani 更新时间:8/3/2023 访问量:55

问:

我正在尝试创建一个 YouTube 抓取器网页(用于教育目的;我永远不会发表它。只是想用它来学习)。我目前拥有的是一个网页,其中包含一个文本框,该文本框采用搜索查询和搜索按钮。当按下搜索按钮时,文本框的内容通过 Ajax post 请求(下面的代码)发送到 Python flask 文件,我使用一些库来搜索 youtube,然后 Python 文件将搜索结果链接打印到终端。我希望发生的事情是将搜索结果显示在我的网页上供用户阅读,但我一生都无法弄清楚如何让 Flask Python 文件将其结果发送到 HTML 页面。

index.html:

<body>
    <center>
        <span>
            <img src="{{ url_for('static', filename='assets/logo.png') }}" style="float: left;" id="logo">
            <input type="text" class="textbox" id="searchbar" style="width: 500px; height: 30px">
            <button style="height: 30px" onclick="performPost()">Search</button>
        </span>

    </center>
    
</body>

<script src="https://code.jquery.com/jquery-3.6.0.js"></script>
<script>
    function performPost(){
        $.ajax({
            type: "POST",
            url: "{{  url_for('search')  }}",
            data: {"search" : document.getElementById("searchbar").value},
        })
    }
</script>

main.py:

import urllib.request
import urllib.parse
import re
from flask import Flask, render_template, request

def searchSite(searchInput):

    query_string = urllib.parse.urlencode({"search_query" : searchInput})
    html_content = urllib.request.urlopen("http://www.youtube.com/results?" + query_string)
    search_results = re.findall(r'watch\?v=(.{11})', html_content.read().decode())
    return (search_results)

app = Flask(__name__)

@app.route('/')
def index():
    return render_template('index.html', text = "heehee")

@app.route('/index.html', methods=['POST', 'GET']) #NOTE: i just changed this line. It used to say @app.route('/', methods=['POST', 'GET'])
def search():
    if request.method == 'POST':
        data = request.form
        searchQuery = data.getlist('search')[0]
        searchResults = searchSite(searchQuery)
        searchList = []
        for i in range(10):
            searchList.append("http://www.youtube.com/watch?v=" + str(searchResults[i]))
        
        print(searchList)

        return render_template('index.html', name = "jaaa")


if __name__ == '__main__':
    app.run(
        host = '127.0.0.1',
        port = 5001,
        debug = True
    )

输出到终端:输出.png

python html ajax flask 帖子

评论

0赞 Phix 8/2/2023
你有两个不同的 app.route(“/”) 函数,可能不是你所追求的
0赞 Matheus Brito 8/2/2023
有两条通往根的路线!你需要解决这个问题。之后,你可以只使用 render_template 方法,将列表传递给 html 页面;返回 render_template('results.html', data=searchResults)
0赞 JBatswani 8/2/2023
@MatheusBrito我应该如何修复它?我应该只分配一个任意目录位置吗?

答:

0赞 Detlef 8/2/2023 #1

发送 AJAX 请求时,页面不会自动重新呈现。开发人员负责将相关数据插入到页面中。

以下示例演示如何在回调中向页面添加响应。

import urllib.request
import urllib.parse
import re
from flask import Flask, render_template, request

def searchSite(searchInput):
    query_string = urllib.parse.urlencode({"search_query" : searchInput})
    html_content = urllib.request.urlopen("http://www.youtube.com/results?" + query_string)
    search_results = re.findall(r'watch\?v=(.{11})', html_content.read().decode())
    return (search_results)

app = Flask(__name__)

@app.route('/')
def index():
    return render_template('index.html')

@app.post('/')
def search():
    data = request.form
    search_query = data.get('search')
    search_results = searchSite(search_query)
    search_list = []
    for i in range(10):
        search_list.append("http://www.youtube.com/watch?v=" + str(search_results[i]))

    print(search_list)
    return render_template('results.html', **locals())
HTML (./templates/index.html)
<!DOCTYPE html>
<html>
<head>
    <meta charset="utf-8">
    <meta name="viewport" content="width=device-width, initial-scale=1">
    <title></title>
</head>
<body>
    <center>
        <span>
            <img src="{{ url_for('static', filename='assets/logo.png') }}" style="float: left;" id="logo" />
            <form onsubmit="handleSubmit(event)">
                <input type="text" class="textbox" id="searchbar" style="width: 500px; height: 30px">
                <button type="submit" style="height: 30px">Search</button>
            </form>
        </span>
        
        <div id="results"></div>
    </center>


    <script src="https://code.jquery.com/jquery-3.6.0.js"></script>
    <script>
        function handleSubmit(event) {
            event.preventDefault();

            $.ajax({
                type: "POST",
                url: "{{  url_for('index') }}",
                data: { search : $('#searchbar').val() },
            }).then(data => {
                $('#results').html(data);
            });
        }
    </script>
</body>
</html>
HTML (./templates/results.html)
{% for result in search_list -%}
    <div>
        <a href="{{ result }}">Result {{  loop.index }}</a>
    </div>
{% endfor -%}

对服务器的传统请求会导致页面被完全重新加载和呈现。这需要时间,为用户阻止页面并使执行不那么流畅,但由浏览器自动完成。另一方面,AJAX 调用旨在在后台加载页面的各个部分,并使页面适应环境。在这种情况下,将数据输入到页面中。
您成功发送了请求,但忽略了服务器的响应。 等待服务器的响应,并将元素的内容替换为接收到的 HTML 数据的 id。
由于您只替换了页面的一部分,因此您不需要整个模板,只需要摘录,因此第二个模板。
如前所述,数据传输是一个异步过程,必须等待。为此,对 Promise 做出反应的块。这里提到的一种解决方案是,一旦任务完成,块中传递的函数就会被调用。另一种可能性是中断执行并使用 await 挂起所有后续命令,直到处理完成。但是,这需要将执行函数定义为异步
then(data => { $('#results').html(data); }resultsresults.htmlthenthen

评论

0赞 JBatswani 8/3/2023
谢谢!这个解决方案非常有效!如果你不介意我问一些问题:1.这条线是做什么的?这似乎是我错过的非常重要的东西 2.正如你所说,这种方法和重新渲染有什么区别?3. 为什么我需要“results.html”?提前感谢您的回答!then(data => { $('#results').html(data); }
0赞 Detlef 8/3/2023
我在回答中添加了一个解释。如果您还有其他问题,请随时提问。