【问题标题】:Rendering Flask template show the HTM page twice渲染 Flask 模板两次显示 HTM 页面
【发布时间】:2021-11-11 11:00:16
【问题描述】:

我有一个烧瓶路由渲染一个包含数据帧表的模板 (method1_result.html)。单击表格行会将单元格值发送到另一个烧瓶路由以呈现新模板(method2_result.html)。最后一个操作显示了一个与 Cell Clicked 相关的新结果,但新的 html 页面 (method1_result.html) 显示了两次结果。

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

@app.route("/method2",methods=['POST', 'GET'])
def method2():
    if request.method == 'POST': 
     # get info here to render page!
        .
        .
        return render_template('method2_result.html',var1=var1)     

method1.html

{% block content %}

<script src="https://ajax.googleapis.com/ajax/libs/jquery/3.2.1/jquery.min.js"></script>
<br/>
        <h3 align="center" style="color:blue" style="font-family:verdana">Method1 Result</h3> 
<br/>

<div class="container-fluid">
<table id="table" class="table table-striped table-bordered" style="width: 100%">
    <thread>
        <tr>
            {% for header in table[0].keys() %}
            <th>{{header}}</th>
            {% endfor %}
        </tr>
    </thread>
    <tbody>
        {% for row in table %}
        
        <tr class='clickable-row'>
            <td>{{row['Field1']}}</td>
            <td>{{row['Field2']}}</td>
            <td>{{row['Field3']}}</td>
            <td>{{row['Field4']}}</td>
        </tr>
        {% endfor %}
    </tbody>
</table>
</div>

<script>
highlight_row();
function highlight_row(var1='') {
    var table = document.getElementById('table');
    var cells = table.getElementsByTagName('td');

    for (var i = 0; i < cells.length; i++) {
        // Take each cell
        var cell = cells[i];
        // do something on onclick event for cell
        cell.onclick = function () {
            // Get the row id where the cell exists
            var rowId = this.parentNode.rowIndex;

            var rowsNotSelected = table.getElementsByTagName('tr');
            for (var row = 0; row < rowsNotSelected.length; row++) {
                rowsNotSelected[row].style.backgroundColor = "";
                rowsNotSelected[row].classList.remove('selected');
            }
            var rowSelected = table.getElementsByTagName('tr')[rowId];
            rowSelected.style.backgroundColor = "yellow";
            rowSelected.className += " selected";

            msg = 'The Failure Message : ' +   rowSelected.cells[6].innerHTML;
            var var1 = rowSelected.cells[3].innerHTML;
            
            $.ajax({
            url:"/method2",
            method:"POST",
            data:{var1:var1},
            success:function(data)
            { 
                $('tbody').html(data);
                $('tbody').append(data.htmlresponse);
            },
        })
           
        }
    }
}
</script>
{% endblock %}

method2.html

{% block content %}

<script src="https://ajax.googleapis.com/ajax/libs/jquery/3.2.1/jquery.min.js"></script>

<br/>
<h4 align="center" style="color:blue" style="font-family:verdana">Method2 result</h4><br/>
<br/>

<table id="table" class="table table-striped table-bordered table-hover" style="width: 100%">
    <thread>
        <tr>
            {% for header in table1[0].keys() %}
            <th>{{header}}</th>
            {% endfor %}
        </tr>
    </thread>
    <tbody>
        {% for row in table1 %}
        <tr>
            <td>{{row['Start']}}</td>
            <td>{{row['OperationID']}}</td>
            <td style="color:red">{{row['Failure Message1']}}</td>
        </tr>
        {% endfor %}
    </tbody>
</table>
{% endblock %}

不确定我做错了什么?

【问题讨论】:

  • 不确定你的意思 - 它显示了两次结果。您究竟希望输出是什么样的?你想只看到新页面还是什么?
  • 我没有显示一个带有表格内容的 html 表格,而是在一页上看到 2 个类似的视图。
  • 我只需要看到一个页面呈现一个表格作为结果。
  • 向我们展示两个页面的 html 代码
  • 我更新了两个 html 页面的部分。

标签: python flask jinja2


【解决方案1】:
  1. 在您的代码中,您正在执行异步调用 (ajax)。异步调用不会重新加载页面。这意味着当结果(即method2_result.html)进来时,用户仍然在method1_result.html上。

  2. 您的代码还说只需将整个 method2_result.html 附加到 method1_result.html 页面。事实上,你做了两次,因为你有

    // First you append the entire response i.e. the entire method2 result
    $('tbody').html(data);
    // Then you try to do it a second time but just the 'htmlresponse' (not sure where you are getting this fro
    $('tbody').append(data.htmlresponse);
  1. 如果您想用method2_result 的全部内容替换整个页面(method1_result),那么您不需要Ajax 调用。用创建表单的代码替换该 ajax 调用,使用要传递给服务器的数据的值创建输入元素,然后提交表单。由于这不是 ajax 调用,它将加载一个新页面,即 method2.html
    var form = document.createElement("form");
    form.method = "POST";
    form.action = "/method2";   

    var elem = document.createElement("input"); 
    elem.name= var1;
    elem.value= var1;
    
    form.appendChild(elem1);  
    document.body.appendChild(form);

    form.submit();
  1. 如果你不想替换整个页面(也许你想用新页面替换现有页面的正文),那么你不能只做append这意味着添加到现有内容,除非您先清除了现有内容。您有 2 个选择

选项 1

    $('tbody').empty() // Remove the current contents
    $('tbody').append(data); // Add the new contents

选项 2

    $('tbody').html(data)

【讨论】:

  • 选项 1 和 2 仍然显示包含重复内容的页面。 document.createElement 准确地显示了我想看到的内容,但没有将变量 var1 传递给烧瓶路线。
  • 添加显示重复内容的屏幕截图。还可以搜索 * 以了解如何创建表单并通过 javascript 即时提交。我可能遗漏了一些东西,但我的代码仅供参考