【问题标题】:How to send selected data from a datatable?如何从数据表中发送选定的数据?
【发布时间】:2018-03-13 08:19:22
【问题描述】:

我接受了一些用户输入,生成了一个我可以display 的表格。现在我想允许用户选择一些数据,然后将这些数据发送回另一个函数,在那里进行进一步处理。对于我用于演示目的的玩具示例,它可能如下所示:

很遗憾,我没有这样做。关键部分大概是thisjquery部分(完整代码可以在下面找到):

$('#send_data').bind('click', function() {
  $.getJSON('/_selected_data', {
    sel_data: table.rows().data().toArray()

  }, function(data) {
    alert('This worked')
  });
  return false;
});

以及我的 Python 代码的这一部分:

@app.route('/_selected_data')
def get_selected_data():

    sel_data = request.args.get('sel_data')

当我打印sel_data 时,它会打印None,当我使用requests.json 时,它也不起作用;理想情况下,可以将结果作为具有相同列标题的 pandas 数据框再次获得。

我将如何正确地做到这一点?另外,如果用户没有选择任何数据,那么当然应该返回整个表格。

这是完整的代码:

from flask import Flask, render_template, request, jsonify
import pandas as pd
import numpy as np
import json

# just for reproducibility
np.random.seed(0)

# Initialize the Flask application
app = Flask(__name__)


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


@app.route('/_get_table')
def get_table():
    a = request.args.get('a', type=int)
    b = request.args.get('b', type=int)

    df = pd.DataFrame(np.random.randint(0, 100, size=(a, b)), columns=['C1', 'C2'])

    return jsonify(number_elements=a * b,
                   my_table=json.loads(df.to_json(orient="split"))["data"],
                   columns=[{"title": str(col)} for col in json.loads(df.to_json(orient="split"))["columns"]])


@app.route('/_selected_data')
def get_selected_data():

    sel_data = request.args.get('sel_data')
    print(sel_data)

    return jsonify(dummy_data=1)


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

还有我的index.html

<!DOCTYPE html>
<html lang="en">
  <head>
    <link href="https://netdna.bootstrapcdn.com/bootstrap/3.0.0/css/bootstrap.min.css" rel="stylesheet">
    <link href="https://cdn.datatables.net/1.10.16/css/jquery.dataTables.min.css" rel="stylesheet">
  </head>
  <body>
    <div class="container">
      <div class="header">
        <h3 class="text-muted">Create a pretty table</h3>
      </div>

      <div>
        <p>Number of rows</p>
        <input type="text" size="5" id="a" value="10">
        <p>Number of columns</p>
        <input type="text" size="5" id="b" value="2">

        <p><a href="javascript:void();" id="calculate">get a pretty table</a></p>
        <p><a href="javascript:void();" id="send_data">send selected data</a></p>
         <p>Result</p>
        <p>Number of elements:</p>
          <span id="elements">Hallo</span><br>
          <table id="a_nice_table" class="table table-striped">Here should be a table</table>
      </div>
    </div>
    <script src="https://code.jquery.com/jquery-1.12.4.js" type="text/javascript"></script>
    <script src="https://cdn.datatables.net/1.10.16/js/jquery.dataTables.min.js" type="text/javascript"></script>
    <script type="text/javascript">
      $(document).ready(function() {
        var table = null;
        $('#calculate').bind('click', function() {
          $.getJSON('/_get_table', {
            a: $('#a').val(),
            b: $('#b').val()
          }, function(data) {
            $("#elements").text(data.number_elements);
            if (table !== null) {
              table.destroy();
              table = null;
              $("#a_nice_table").empty();
            }
            table = $("#a_nice_table").DataTable({
              data: data.my_table,
              columns: data.columns
            });
          });
          return false;
        });
        $('#send_data').bind('click', function() {
          $.getJSON('/_selected_data', {
            sel_data: table.rows().data().toArray()

          }, function(data) {
            alert('This worked')
          });
          return false;
        });
      });
    </script>
  </body>
</html>

【问题讨论】:

    标签: python jquery ajax flask datatables


    【解决方案1】:

    这是我对您的问题的尝试解决方案。我假设用户一次只能选择一行。

    index.html

    <!DOCTYPE html>
    <html lang="en">
      <head>
        <link href="https://netdna.bootstrapcdn.com/bootstrap/3.0.0/css/bootstrap.min.css" rel="stylesheet">
        <link href="https://cdn.datatables.net/1.10.16/css/jquery.dataTables.min.css" rel="stylesheet">
      </head>
      <body>
        <div class="container">
          <div class="header">
            <h3 class="text-muted">Create a pretty table</h3>
          </div>
    
          <div>
            <p>Number of rows</p>
            <input type="text" size="5" id="a" value="10">
            <p>Number of columns</p>
            <input type="text" size="5" id="b" value="2">
    
            <p><a href="javascript:void();" id="calculate">get a pretty table</a></p>
            <p><a href="javascript:void();" id="send_data">send selected data</a></p>
             <p>Result</p>
            <p>Number of elements:</p>
              <span id="elements">Hallo</span><br>
              <table id="a_nice_table" class="table table-striped">Here should be a table</table>
          </div>
        </div>
        <script src="https://code.jquery.com/jquery-1.12.4.js" type="text/javascript"></script>
        <script src="https://cdn.datatables.net/1.10.16/js/jquery.dataTables.min.js" type="text/javascript"></script>
        <script type="text/javascript">
          $(document).ready(function() {
            var table = null;
            var selected = null;
            $('#calculate').bind('click', function() {
              $.getJSON('/_get_table', {
                a: $('#a').val(),
                b: $('#b').val()
              }, function(data) {
                $("#elements").text(data.number_elements);
                if (table !== null) {
                  table.destroy();
                  table = null;
                  $("#a_nice_table").empty();
                }
                table = $("#a_nice_table").DataTable({
                  data: data.my_table,
                  columns: data.columns
                });
                var drawn_table = document.getElementById('a_nice_table'),
                    selected = drawn_table.getElementsByClassName('selected');
                drawn_table.onclick = highlight;
                function highlight(e) {
                  if (selected[0]) selected[0].className = '';
                  e.target.parentNode.className = 'selected';
                }
              });
              return false;
            });
            $('#send_data').bind('click', function() {
              var selected = $("tr.selected").html();
              if (selected != null) {
                console.log("<thead>" + $("#a_nice_table thead").html() + "</thead><tbody><tr>" + selected + "</tr></tbody>");
                $.getJSON('/_selected_data', {
                  sel_data: "<thead>" + $("#a_nice_table thead").html() + "</thead><tbody><tr>" + selected + "</tr></tbody>"
                }, function(data) {
                  alert('This worked');
                });
              } else {
                console.log($("#a_nice_table").html());
                $.getJSON('/_selected_data', {
                  sel_data: $("#a_nice_table").html()
                }, function(data) {
                  alert('This worked');
                });
              }
              return false;
            });
          });
        </script>
      </body>
    </html>
    

    app.py

    from flask import Flask, render_template, request, jsonify
    import pandas as pd
    import numpy as np
    import json
    
    # just for reproducibility
    np.random.seed(0)
    
    # Initialize the Flask application
    app = Flask(__name__)
    
    
    @app.route('/')
    def index():
        return render_template('index.html')
    
    
    @app.route('/_get_table')
    def get_table():
        a = request.args.get('a', type=int)
        b = request.args.get('b', type=int)
    
        df = pd.DataFrame(np.random.randint(0, 100, size=(a, b)), columns=['C1', 'C2'])
    
        return jsonify(number_elements=a * b,
                       my_table=json.loads(df.to_json(orient="split"))["data"],
                       columns=[{"title": str(col)} for col in json.loads(df.to_json(orient="split"))["columns"]])
    
    
    @app.route('/_selected_data')
    def get_selected_data():
    
        sel_data = request.args.get('sel_data')
        df_list = pd.read_html("<table>" + sel_data + "</table>")
        df = pd.concat(df_list)
        print(df)
    
        return jsonify(dummy_data=1)
    
    
    if __name__ == '__main__':
        app.run(debug=True)
    

    所以基本上发生的情况是,在随机生成表后,我必须创建几个变量(drawn_tableselected)来跟踪表及其选定的行。到目前为止,选择行的时间没有视觉上的变化,但是如果您想要进行任何 CSS 修改来表示何时选择了行,则取决于您。当用户确实单击一行时,该行将获得“已选择”的类分配,并且任何其他行都将被取消选择。这是为了让 JQuery 在将其发送回服务器时知道选择了哪一行。

    然后在send_data 链接中,我将找到具有“选定”类 (tr.selected) 的 tr(表格行)元素,并获取该元素内的 html 代码。如果元素存在,那么我会将 html 连同表头信息作为 JSON 发送到烧瓶。如果没有tr.selected元素,那么html代码显然是未定义的,所以代码会运行块的else部分并发送整个表。

    app.py 中,我读取了 JSON 值,它是一串 HTML 代码。由于 Pandas 有一个 read_html 方法,我可以将 HTML 字符串传递给该方法以创建数据帧列表。然后我将concat 数据框列表作为我的最终df

    您可以在 Python 的控制台日志 (print(df)) 中查看数据帧的结果。您还可以在浏览器检查器中看到 html 代码结果,因为我添加了一些 console.log 语句。

    【讨论】:

    • 谢谢你!我只能在大约两个小时内测试它;然后会回复您,包括投票等,
    • 没问题!我刚刚查看了我的答案并添加了一些编辑。还希望将此 SO post 归功于在表格中选择行的代码。 :)
    • 如宣传的那样工作,非常感谢(赞成,很快就会接受)!不过,我仍然需要花一点时间来完成它:)
    • @Cleb 太棒了!如果您需要更详细的解释,请随时给我发消息。
    • 感谢您的报价!我自己做不到,但我想我现在理解了代码(但可能很快就会有另一个问题;))。
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 2020-06-11
    • 2016-11-25
    • 1970-01-01
    • 1970-01-01
    • 2017-10-18
    • 1970-01-01
    • 2012-07-21
    相关资源
    最近更新 更多