web2py - ajax 调用 returns 404 或无法处理参数

web2py - ajax call returns 404 or fails to process parameters

我在我的控制器中定义了一个函数:

def get_config_values():
    path = unescape(request.vars['path'])
    config = get_config_as_dict(path)
    return dict(config)

在我看来我使用 jQuery $.ajax() 在视图中调用它:

$.ajax({
      url: "{{=URL('get_config_values.json')}}", 
      contentType: "application/json; charset=utf-8", 
      data: {
         path: page_path,
      },
      error: function(x, y, z) {
         show_error(x.responseText, y, z);
         hide_drawer();
      },
      success: function(data) {
         $('#drawer_content').html(data);
      },
      type: 'POST',
   });

简而言之,我无法让它工作。

Web2py 在这里似乎表现得很奇怪——为了让 POST 工作,我必须明确设置 contentType: "application/json" 否则我也会在那里看到 404,尽管 data:'json' 已经存在了。

有没有其他人看到并解决了这种行为?我不在乎调用是 GET 还是 POST,我只希望它能正常工作!

有一些问题。首先,当一个 web2py 动作 return 是一个字典时,web2py 寻找一个关联的视图来执行(基于动作的路径和扩展名)。在这种情况下,它将查找路径为 /views/controller_name/get_config_values.json 的视图。如果它没有找到该视图,它可能会尝试使用 generic.json 视图,但前提是您通过 response.generic_patterns 明确启用了通用视图(在脚手架应用程序中,所有通用视图都由默认,但仅适用于本地请求)。否则,您将收到 404 错误(如果您在浏览器开发人员工具中检查错误消息的 body,您应该会看到有关无效视图的消息)。

其次,通过 jQuery 到 post JSON,您必须将 Javascript object 转换为 JSON 字符串:

data: JSON.stringify(
    {
        path: page_path
    }
),

根据以上内容,您现在应该在服务器上的 request.vars.path 中具有 page_path 的值。

最后,如果您从 web2py 请求 .json URL,它会将 Content-Type 响应 header 设置为 "application/json"。但是,根据您的 Javascript 代码,您似乎想要 return HTML(假定您将结果放入页面上的 div)。因此,您可能不应该在请求中使用 .json 扩展名(您也可以通过设置 dataType: 'html' 明确告诉 jQuery 响应是 HTML)。

所以,请尝试以下操作:

$.ajax({
  url: "{{=URL('get_config_values')}}", 
  contentType: "application/json; charset=utf-8", 
  data: JSON.stringify({
     path: page_path,
  }),
  error: function(x, y, z) {
     show_error(x.responseText, y, z);
     hide_drawer();
  },
  success: function(data) {
     $('#drawer_content').html(data);
  },
  type: 'POST',
});

然后创建一个 get_config_values.html 视图,从 returned 字典生成所需的 HTML,或者直接使用 get_config_values 函数 return一个 HTML 字符串。

如果您确实想要 return JSON 到浏览器,那么您需要更改 success 回调以在尝试放置之前处理 JSON它在 div.