从JavaScript返回JSON到Python

1 投票
2 回答
738 浏览
提问于 2025-04-15 22:30

我正在写一个简单的App Engine应用。

我有一个简单的页面,用户可以在谷歌地图上移动一个标记。每次用户放下标记时,我想把经纬度返回给我的Python应用。

function initialize() {

  ... // Init map

  var marker = new GMarker(center, {draggable: true});
  GEvent.addListener(marker, "dragend", function() {
    // I want to return the marker.x/y to my app when this function is called ..
  });

}

根据我(确实有限的)知识,我应该:

1). 在上面的监听器回调中返回一个包含我需要数据的JSON结构。

2). 在我的webapp.RequestHandler处理类中,尝试在post方法中获取这个JSON结构。

我非常希望能在不重新加载页面的情况下将这个JSON数据传回应用(因为到目前为止,我使用各种post/form.submit方法时,页面都会重新加载)。

有没有人能给我一些伪代码或示例,告诉我怎么实现我想要的功能?

谢谢。

2 个回答

7

为了防止页面重新加载,我们可以在网页上使用AJAX来处理这个问题。

如果你用jquery的话,可以这样做:

$("#testform").submit(function() {
    // post the form values via AJAX...
    var postdata = {lat: $("#lat").val(), long: $("#long").val()} ;
    $.post('/submit', postdata, function(data) {
        // and set the location with the result
        $("#location").html(data['location']) ;
       });
    return false ;
    });

假设你有一个这样的网页:

<p>Enter lat and long:</p>
<form id="testform" action="#" method="post">
    <p>
    <label for="lat">Lat:</label>
    <input type="text" id="lat" /> <br />
    <label for="long">Long:</label>
    <input type="text" id="long" /> <br />

    <input type="submit" value="Get Location" />
    </p>
</form>

<p>The location is:</p><p id="location">(enter lat and long above)</p>

然后让Python代码返回一个包含位置的JSON字典。

最后,我建议你设置一个优雅的备用方案:如果用户禁用了JavaScript,就正常提交到比如说 /getlocation 并重新加载页面;然后让JavaScript覆盖这个操作,提交到一个特殊的URL,这个URL会返回JSON数据,比如 /getlocationajax

1

如果你不想让页面自动更新,那你需要用到 XMLHttpRequest。在这个例子中,我使用了客户端的 function Request(function_name, opt_argv) 和服务器端的 RPCHandler,这些来自于这个 Google App Engine 的例子。我还没有测试过这个,但大概会是这样的:

客户端的 Javascript

function initialize() {

  ... // Init map

  var marker = new GMarker(center, {draggable: true});
  GEvent.addListener(marker, "dragend", function(position) {
    Request('update_marker_position', [ unique_identifier, position.lat(), position.lng() ] );
  });

}

服务器端的 Python

# Create database model for LatLng position
class LatLng(db.Model):
    lat = db.IntegerProperty()
    lng = db.IntegerProperty()

...

class RPCMethods:
    """ Defines the methods that can be RPCed.
    NOTE: Do not allow remote callers access to private/protected "_*" methods.
    """

    def update_marker_position(self, *args):
        # args[0] - unique identifier, say GAE db key
        # args[1] - lat
        # args[2] - lng
        # Note: need to do some checking that lat and lng are valid
        
        # Retrieve key and update position
        position = LatLng.get(db.Key(args[0])
        if position:
            position.lat = args[1]
            position.lng = args[2]
        else:
            position = LatLng(
                lat= args[1], 
                lng= args[2]
            )
        position.put()
        
        payload = {
            'lat': args[1],
            'lng': args[2],
        }
        return payload

你需要在页面加载时创建数据库条目,并在客户端保存数据库的键。你也可以使用其他唯一的标识符。在这个例子中,我假设你把它存储为一个全局变量 'unique_identifier'。

另外,你还需要添加一个回调函数来处理返回的数据(里面有 'lat' 和 'lng' 这两个值)。根据这个例子,我认为你只需要把你的回调函数作为 opt_argv 数组中的第一个参数传给 Request。希望这能帮到你。

撰写回答