【问题标题】:Round-trip passing of data from Javascript to Redis (via Python) and back?数据从 Javascript 到 Redis 的往返传递(通过 Python)并返回?
【发布时间】:2016-06-05 09:38:11
【问题描述】:

我正在重构一个我自己用作学习工具的项目,它是一个 HTML5 画布游戏,其中我有一个用 javascript 对象和画布构建的六边形网格。一切都存储在 javascript 对象结构中。

我正在尝试更多地了解 Python。我设置了一个基本的 Python Flask 路由,能够将 AJAX 请求从 javascript 发送到 Flask 路由,能够提交到 Redis,能够从 Redis 检索......但我似乎无法弄清楚是什么我缺少将信息从 Python 传递回 javascript 对象的部分。

HTML:

<head>
    <script type=text/javascript src="{{ url_for('static', filename='jquery-2.2.0.min.js') }}"></script>

</head>
<script type="text/javascript"> 
$(function() {
    var data = 
        {
            row: '3',
            col: '3',
        };
    $('#sendBtn').click(function() {
        $.ajax({
            type: 'POST',
            url: '/saveMap',
            contentType: "application/json; charset=utf-8",
            data: JSON.stringify(data),
            success: function(response) {
                console.log(response.row)
            },
            error: function(error) {
                console.log(error);
            }
        });
    });
});
</script>

<body>
    <button id="sendBtn" class="btn btn-lg btn-primary btn-block" type="button">Send</button>

</body>

</html>

Python: 从烧瓶进口烧瓶,render_template,json,请求 导入redis

app = Flask(__name__)
r = redis.Redis("localhost")

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

@app.route('/saveMap',methods=['POST'])
def saveMap():
    if request.method == "POST":
        r.set("test", request.json)
        result = r.get("test")
        return result

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

因此,当单击#sendBtn 时,请求会通过,然后返回,并在“网络”选项卡中显示为响应

{u'col': u'3', u'row': u'3'}

但是在 AJAX 调用的成功部分,当我尝试调用 response.row 时,它给了我一个“未定义”。

我觉得我很接近,我在这里错过了什么?

【问题讨论】:

    标签: javascript python ajax flask redis


    【解决方案1】:

    问题是r.get("test") 返回一个str看起来 像一个字典。使用jsonifypickle.dumpspickle.loads 将解决您的问题。

    from flask import Flask, render_template, request, jsonify
    import redis, pickle
    
    app = Flask(__name__)
    r = redis.Redis("localhost")
    
    @app.route("/")
    def main():
        return render_template('index.html')
    
    @app.route('/saveMap',methods=['POST'])
    def saveMap():
        if request.method == "POST":
            r.set("test", pickle.dumps(request.json))
            result = pickle.loads(r.get("test"))
            return jsonify(result)
    
    if __name__ == "__main__":
        app.run(debug=True)
    

    编辑:从使用 eval 更改为使用 pickle 只是为了安全起见,正如提到的爬行动物

    【讨论】:

    • 这比我在上述答案中所做的随机字符串操作解决方案要好得多。这甚至使得接收 javascript 甚至不需要 JSON.parse() 对象,它只是立即作为 javascript 对象进入。非常感谢!
    • 永远不要在网络应用程序中使用eval,那里的攻击向量太多了......
    • 很公平。编辑为使用pickle 而不是eval
    【解决方案2】:

    尝试console.log(response) 看看实际返回的内容。如果返回的是 JSON,您可能仍需要对其进行解析,然后才能像对象一样访问它,并且它可能会以某种方式被包装,具体取决于您的服务器处理中是否涉及中间件。

    【讨论】:

    • 这会在控制台中生成{u'col': u'3', u'row': u'3'}。我进一步做了console.log(typeof(response)) 并返回string。太好了……这是一个看起来像 JSON 的字符串。
    • 另外,如果我执行JSON.parse(repsonse),我会收到此错误:SyntaxError: JSON.parse: expected property name or '}' at line 1 column 2 of the JSON data 那么,它是不是格式错误的 JSON?
    • “u”可能是个问题。检查您的服务器以确保它正在尝试发回序列化的 JSON(可能通过 json.dumps)而不是字典的 Python 字符串表示形式。
    • 您的回答不太正确,但它引导我走上了正确的道路。事实证明JSON.parse() 不喜欢那些u 字符并且它更喜欢双引号而不是单引号。因此,我必须执行以下操作才能使其正常工作:response = response.replace(/u/g, ""); response = response.slice(1, response.length - 1); response = response.replace(/'/g, '"'); var responseJSON = JSON.parse(response);
    猜你喜欢
    • 2016-04-11
    • 2017-07-23
    • 1970-01-01
    • 2017-09-26
    • 2012-11-12
    • 2011-08-10
    • 2016-04-29
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多