使用Flask

时间:2015-05-04 22:04:09

标签: javascript flask handsontable

我尝试使用Flask从HandsOnTable加载和保存数据。我在these instructions之后使用ajax加载和保存(检索和发送)数据。我已经设法从返回JSON字典的URL中将数据加载到表中,但我还没弄清楚如何发送数据存储在我的数据库中。

以下是javascript的相关部分:

Handsontable.Dom.addEvent(save, 'click', function() {
    // save all cell's data
    ajax('/json/save.json', 'GET', JSON.stringify({data: hot.getData()}), function (res) {
      var response = JSON.parse(res.response);

      if (response.result === 'ok') {
        exampleConsole.innerText = 'Data saved';
      }
      else {
        exampleConsole.innerText = 'Save error';
      }
    });
  });

所以希望从HandsOnTable获取数据,将其转换为这种格式的大型JSON表:

{'data' : [[row 1], [row 2],...]}

以下是相关的Flask视图功能:

@app.route('/json/save.json', methods = ['GET', 'POST'])
@login_required
def jsonSave():
    data = request.form['data']
    #Do stuff to load data into database
    return 'ok'

删除不相关的部分。基本上我的问题是如何使保存功能的data = request.form['data']部分工作,并将其转换为一个简单的行列表?

顺便提一下,为什么这很困难的一部分原因是我无法通过ajax调用查看究竟是什么发送到view函数。有没有办法可以看到,所以我可以更轻松地调试这样的问题?打印声明似乎不适用于视图功能(我无法在控制台中看到它们)。

非常感谢, 亚历

更新根据ZekeDroid的说明更改(再次):

Handsontable.Dom.addEvent(save, 'click', function() {
// save all cell's data
console.log(JSON.stringify({data: hot.getData()}));
ajax('/json/save/{{well['id']}}', 'POST', JSON.stringify({data: hot.getData()}), function (res) {
  var response = JSON.parse(res.response);

  if (response.result === 'ok') {
    exampleConsole.innerText = 'Data saved';
  }
  else {
    exampleConsole.innerText = 'Save error';
  }
});

});

@app.route('/json/save/<int:well_id>', methods = ['GET', 'POST'])
@login_required
def jsonSave(well_id):
    jsonData = request.get_json()
    print 'jsonData:', jsonData
    data = jsonData['data']
    print 'data:', data
    #Insert table into database
    print 'saving', well_id
    return json.dumps(True)

调试输出: 基本上,看起来Flask在调用jsonData = request.get_json()时没有加载json对象。但是,console.log(JSON.stringify({data: hot.getData()}));看起来还不错。

以下是浏览器和Flask控制台的输出:

浏览器:

{"data":[["01/01/15",100,300,200,96],["01/02/15",200,500,300,50],["01/03/15",300,600,400,80],["01/01/15",100,300,200,96],["01/02/15",200,500,300,50],["01/03/15",300,600,400,80],["01/01/15",100,300,200,96],["01/02/15",200,500,300,50],["01/03/15",300,600,400,80],[null,null,null,null,null]]}
samples.js:94 POST http://127.0.0.1:5000/json/save/1 500 (INTERNAL SERVER ERROR)

烧瓶中:

jsonData: None
127.0.0.1 - - [13/May/2015 11:41:31] "POST /json/save/1 HTTP/1.1" 500 -
Traceback (most recent call last):
  File "C:\Users\aschmitt\Envs\PetroTools\lib\site-packages\flask\app.py", line
1836, in __call__
    return self.wsgi_app(environ, start_response)
  File "C:\Users\aschmitt\Envs\PetroTools\lib\site-packages\flask\app.py", line
1820, in wsgi_app
    response = self.make_response(self.handle_exception(e))
  File "C:\Users\aschmitt\Envs\PetroTools\lib\site-packages\flask\app.py", line
1403, in handle_exception
    reraise(exc_type, exc_value, tb)
  File "C:\Users\aschmitt\Envs\PetroTools\lib\site-packages\flask\app.py", line
1817, in wsgi_app
    response = self.full_dispatch_request()
  File "C:\Users\aschmitt\Envs\PetroTools\lib\site-packages\flask\app.py", line
1477, in full_dispatch_request
    rv = self.handle_user_exception(e)
  File "C:\Users\aschmitt\Envs\PetroTools\lib\site-packages\flask\app.py", line
1381, in handle_user_exception
    reraise(exc_type, exc_value, tb)
  File "C:\Users\aschmitt\Envs\PetroTools\lib\site-packages\flask\app.py", line
1475, in full_dispatch_request
    rv = self.dispatch_request()
  File "C:\Users\aschmitt\Envs\PetroTools\lib\site-packages\flask\app.py", line
1461, in dispatch_request
    return self.view_functions[rule.endpoint](**req.view_args)
  File "C:\Users\aschmitt\Envs\PetroTools\lib\site-packages\flask_login.py", lin
e 758, in decorated_view
    return func(*args, **kwargs)
  File "C:\Users\aschmitt\Dropbox\Python\PetroTools\app\views.py", line 236, in
jsonSave
    data = jsonData['data']
TypeError: 'NoneType' object has no attribute '__getitem__'

2 个答案:

答案 0 :(得分:3)

这是一个很好的问题,到目前为止工作很棒!现在,让我们从显而易见的开始。您使用GET请求向Flask发送数据,但实际上您正在尝试POST数据,这就是Python在request中没有任何内容的原因。如果我错了,请纠正我,因为情况可能并非如此,但这是你如何调试它:

你应该在某个地方的shell上运行flask。在这里,您会看到所有print语句,因此,在jsonSave()中,在您定义后立即添加行print data。此外,由于两个原因,您错误地检索数据。首先语法如下:

jsonData = request.get_json()
data = jsonData["data"]

另外,如果您期待状态响应,那么使用JSON响应它可能是值得的,并且可以使用布尔值:

return json.dumps(True)

现在是前端。在将数据发送到服务器之前,只需将其打印到控制台即可。在ajax电话正上方添加此行:

console.log(JSON.stringify({data: hot.getData()}));

这应该足以让你调试双方。在看到并进行更改后,我建议您应该更好地了解错误,但如果没有,请使用您认为相关的输出更新您的问题(例如,如果python在尝试打印时打印空行{ {1}})。

编辑:

能够以您设置路线的方式接收参数不正确。你也为什么要data?相反,试试这个:

save.json

在你的ajax电话中:

@app.route('/json/save/<well_id>', methods = ['GET', 'POST'])
@login_required
def jsonSave(well_id):
    jsonData = request.get_json()
    data = jsonData['data'] # this will fail if it is not a POST request
    print 'data:', data
    #Do stuff to load data into Database
    print 'saving', well_id
    return json.dumps(True)

另外,请发布控制台日志和打印声明。我们现在还在黑暗中。

答案 1 :(得分:1)

为了解决这个问题,我重新开始了。我包含了这些javascript文件:

<script src="https://code.jquery.com/jquery-1.11.1.min.js"></script>
<link rel="stylesheet" media="screen" href="http://handsontable.com/dist/handsontable.full.css">
<script src="http://handsontable.com/dist/handsontable.full.js"></script>

我删除了从旧jsfiddle获取的samples.js文件。我认为这搞砸了。

根据ZekeDroid的建议,我将烧瓶保存功能更改为:

@app.route('/json/save/<int:well_id>', methods = ['GET', 'POST'])
@login_required
def jsonSave(well_id):
    w = Well.query.get(well_id)
    jsonData = request.get_json()
    print 'jsonData:', jsonData
    data = jsonData['data']
    print 'data:', data

    #Load Data dictionary into the database.

    return json.dumps(True)

我用这个替换了jquery save函数:

Handsontable.Dom.addEvent(save, 'click', function() {
    // save all cell's data
    var arr = { data: hot.getData()};
    $.ajax({
    url: '/json/save/{{well['id']}}',
    type: 'POST',
    data: JSON.stringify(arr),
    contentType: 'application/json; charset=utf-8',
    dataType: 'json',
    async: true,
    success: function(msg) {
        console.log(msg);
      }
      });
});

我无法从handontable教程(here)中获取保存功能,所以我使用了接受的答案here。我使用POST是因为如果我理解正确,它没有像GET那样的大小限制,而且我将会发送一些相当大的数组。

删除samples.js文件也破坏了加载功能,所以我将其替换为:

Handsontable.Dom.addEvent(load, 'click', function() {
    var arr = { data: []};
    $.ajax({
    url: '/json/load/{{well['id']}}',
    type: 'GET',
    contentType: 'application/json; charset=utf-8',
    data: JSON.stringify(arr),    
    dataType: 'json',
    async: true,
    success: function(msg) {
        hot.loadData(msg.data);
        console.log('Loaded:');
        console.log(msg.data);
    }
    });
});

这显然与保存功能非常相似。感谢ZekeDroid的所有帮助。

亚历