You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

Flask模板无需JS更新变量:图书管理系统搜索功能失效排查

Flask图书管理系统搜索功能问题排查及无JS实现方案

问题描述

我正在开发基于Flask的图书管理系统,需实现图书搜索功能——在搜索框输入内容后仅显示匹配的图书。已编写HTML模板、Flask后端处理函数及JavaScript请求代码,JS与Python逻辑看似正常,但执行搜索时页面无变化。同时咨询无需JavaScript即可更新Flask模板变量的方法。

相关代码如下:

HTML模板

{% block content %}
<div class="search-area">
    <div class="input">
        <input class="search" type="text" id="search-box" placeholder="Search A Book" autocomplete="off">
        <img src="static/icons/search.svg">
    </div>
</div>

<main id="main-content">
    {% if search_term %}
      {% for book in books %}
        <div class="container">
          <div class="inner-containers" id="{{book['ID']}}" onclick="showReader('{{book['ID']}}')">
            <div class="image-container">
              <img draggable="false" class="book-image" src="{{ url_for('static', filename='thumbnails/' + book['Image']) }}">
            </div>
            <div class="book-details">
              <p class="name">{{ book['Name'] }}</p>
              <p class="author">{{ book['Author'] }}</p>
              <p class="details">{{ book['Date'] }} &#183; {{ book['Genre'] }}</p>
            </div>
          </div>
        </div>
      {% endfor %}
    {% else %}
      {% for book in original_books %}
        <div class="container">
          <div class="inner-containers" id="{{book['ID']}}" onclick="showReader('{{book['ID']}}')">
            <div class="image-container">
              <img draggable="false" class="book-image" src="{{ url_for('static', filename='thumbnails/' + book['Image']) }}">
            </div>
            <div class="book-details">
              <p class="name">{{ book['Name'] }}</p>
              <p class="author">{{ book['Author'] }}</p>
              <p class="details">{{ book['Date'] }} &#183; {{ book['Genre'] }}</p>
            </div>
          </div>
        </div>
      {% endfor %}
    {% endif %}
    
    <p class="section-title">This Month in Horror</p>
  </main>

{% endblock %}

Flask后端代码

@app.route('/home', methods=['GET', 'POST'])
def home():
  books = books_df.books.to_dict('records')
  original_books = books.copy()  # Assuming you want a copy for full data
  search_term = ''  # Initialize empty search term

  if request.method == 'POST':
    # Handle search term
    data = request.get_json()
    search_term = data.get('searchTerm', '').lower()  # Get and lowercase search term

    # Filter books based on search term (if provided)
    if search_term:
      filtered_books = books_df.books[books_df.books['Name'].str.lower().str.contains(search_term)]
      books = filtered_books.to_dict('records')
      print(books)
    return render_template('home.html', books=books, search_term = search_term)  # Pass both variables
  return render_template('home.html', original_books=original_books, search_term = None)

JavaScript代码

<script>
        inputbox = document.getElementById('search-box');

        inputbox.addEventListener('keyup', () => {
        let input = inputbox.value.trim().toLowerCase();

        if (input.length) {
            // Create an XMLHttpRequest object
            const xhr = new XMLHttpRequest();
            xhr.open("POST", "/home"); // Replace with your actual endpoint

            // Set request headers (optional, but recommended for data format)
            xhr.setRequestHeader("Content-Type", "application/json");

            // Send the search term as JSON data
            xhr.send(JSON.stringify({ searchTerm: input }));
        }
    })
        
    </script>

一、AJAX搜索无响应问题排查

页面无变化的核心原因是:JS只发送了请求,但没有处理后端返回的响应内容,后端渲染的新HTML没有替换到页面中。同时还有几处细节需要修正:

1. 补充AJAX响应处理逻辑

修改JS代码,添加onload事件,将后端返回的HTML替换到图书列表区域:

<script>
const inputbox = document.getElementById('search-box');

inputbox.addEventListener('keyup', () => {
    let input = inputbox.value.trim().toLowerCase();
    const xhr = new XMLHttpRequest();
    xhr.open("POST", "/home");
    xhr.setRequestHeader("Content-Type", "application/json");
    
    // 处理后端返回的响应
    xhr.onload = function() {
        if (xhr.status === 200) {
            // 替换图书列表区域的内容
            document.getElementById('main-content').innerHTML = xhr.responseText;
        }
    };
    
    // 输入为空时也发送请求,恢复显示全部图书
    xhr.send(JSON.stringify({ searchTerm: input }));
})
</script>

2. 修复后端变量传递漏洞

当前后端POST分支未传递original_books,但HTML模板的else分支依赖该变量,会导致搜索后清空输入时页面报错。修改后端代码:

@app.route('/home', methods=['GET', 'POST'])
def home():
    books = books_df.books.to_dict('records')
    original_books = books.copy()
    search_term = ''

    if request.method == 'POST':
        data = request.get_json()
        search_term = data.get('searchTerm', '').lower().strip()

        if search_term:
            filtered_books = books_df.books[books_df.books['Name'].str.lower().str.contains(search_term)]
            books = filtered_books.to_dict('records')
        else:
            # 搜索词为空时恢复显示全部图书
            books = original_books
        # 无论是否搜索,都传递original_books变量
        return render_template('home.html', books=books, original_books=original_books, search_term=search_term)
    return render_template('home.html', original_books=original_books, search_term=None)

二、无需JavaScript的搜索实现方案

通过传统表单提交方式实现,完全不需要JS:

1. 修改HTML模板添加表单

将搜索框包裹在表单中,指定提交方式和路由:

{% block content %}
<div class="search-area">
    <div class="input">
        <form method="POST" action="/home">
            <input class="search" type="text" name="searchTerm" id="search-box" placeholder="Search A Book" autocomplete="off" value="{{ search_term or '' }}">
            <button type="submit" style="border: none; background: none; padding: 0;">
                <img src="static/icons/search.svg">
            </button>
        </form>
    </div>
</div>

<!-- 图书列表部分保持不变 -->
<main id="main-content">
    {% if search_term %}
      {% for book in books %}
        <!-- 图书卡片代码 -->
      {% endfor %}
    {% else %}
      {% for book in original_books %}
        <!-- 图书卡片代码 -->
      {% endfor %}
    {% endif %}
    
    <p class="section-title">This Month in Horror</p>
  </main>
{% endblock %}

2. 修改后端处理表单数据

表单提交的是form-data而非JSON,需用request.form获取搜索词:

@app.route('/home', methods=['GET', 'POST'])
def home():
    books = books_df.books.to_dict('records')
    original_books = books.copy()
    search_term = None

    if request.method == 'POST':
        # 从表单中获取搜索词
        search_term = request.form.get('searchTerm', '').lower().strip()

        if search_term:
            filtered_books = books_df.books[books_df.books['Name'].str.lower().str.contains(search_term)]
            books = filtered_books.to_dict('records')
        else:
            # 搜索词为空时显示全部图书
            books = original_books
    # 统一传递所有模板变量
    return render_template('home.html', books=books, original_books=original_books, search_term=search_term)

这种方式的原理是:用户输入关键词后点击搜索按钮(或按回车),表单提交到后端,后端处理后重新渲染整个页面并返回,实现内容更新。优点是无需JS、兼容性好;缺点是每次搜索会刷新整个页面。


内容的提问来源于stack exchange,提问作者Rishit Chakraborty

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.06.26 00:07:51