【问题标题】:How to use AJAX with Google App Engine (Python)如何将 AJAX 与 Google App Engine (Python) 结合使用
【发布时间】:2014-03-29 21:47:54
【问题描述】:

我完全是 AJAX 的新手。我熟悉 HTML/CSS、jQuery 和 GAE 和 Python 的初学者。

为了了解 AJAX 的工作原理,我想知道在下面的示例中如何使用 AJAX(实际代码)。让我们使用一个类似 reddit 的例子,其中投票的上升/下降是 ajaxified:

这是故事类型:

class Story(ndb.Model):
    title = ndb.StringProperty(required = True)
    vote_count = ndb.IntegerProperty(default = 0)

HTML 看起来像这样:

<h2>{{story.title}}</h2>
<div>
    {{story.vote_count}} | <a href="#">Vote Up Story</a>
</div>

AJAX 如何融入其中?

【问题讨论】:

    标签: javascript ajax google-app-engine python-2.7 app-engine-ndb


    【解决方案1】:

    好的,先生,我们开始...一个简单的应用程序,一个故事和无限投票... ;-)

    app.yaml

    application: anotherappname
    version: 1
    runtime: python27
    api_version: 1
    threadsafe: true
    
    default_expiration: "0d 0h 5m"
    
    libraries:
    - name: jinja2
      version: latest
    
    - name: webapp2
      version: latest
    
    handlers:
    - url: .*
      script: main.app
    

    main.py

    import logging
    from controllers import server
    from config import config
    import webapp2
    
    
    app = webapp2.WSGIApplication([
            # Essential handlers
            ('/', server.RootPage),
            ('/vote/', server.VoteHandler)
        ],debug=True, config=config.config)
    
    
    # Extra Hanlder like 404 500 etc
    def handle_404(request, response, exception):
        logging.exception(exception)
        response.write('Oops! Naughty Mr. Jiggles (This is a 404)')
        response.set_status(404)
    
    app.error_handlers[404] = handle_404
    

    models/story.py

    from google.appengine.ext import ndb
    
    
    class Story(ndb.Model):
        title = ndb.StringProperty(required=True)
        vote_count = ndb.IntegerProperty(default = 0)
    

    controllers/server.py

    import os
    import re
    import logging
    import config
    import json
    
    import webapp2
    import jinja2
    
    from google.appengine.ext import ndb
    from models.story import Story
    
    
    class RootPage(webapp2.RequestHandler):
        def get(self):
            story = Story.get_or_insert('Some id or so', title='A voting story again...')
            jinja_environment = self.jinja_environment
            template = jinja_environment.get_template("/index.html")
            self.response.out.write(template.render({'story': story}))
    
    
        @property
        def jinja_environment(self):
            jinja_environment = jinja2.Environment(
                loader=jinja2.FileSystemLoader(
                    os.path.join(os.path.dirname(__file__),
                                 '../views'
                    ))
            )
            return jinja_environment
    
    
    class VoteHandler(webapp2.RequestHandler):
        def post(self):
            logging.info(self.request.body)
            data = json.loads(self.request.body)
            story = ndb.Key(Story, data['storyKey']).get()
            story.vote_count += 1
            story.put()
            self.response.out.write(json.dumps(({'story': story.to_dict()})))
    

    最后

    views/index.html

    <!DOCTYPE html>
    <html>
        <head>
            <base href="/">
            <meta http-equiv="Content-Type" content="text/html; charset=utf-8">
            <script src="//ajax.googleapis.com/ajax/libs/jquery/1.11.0/jquery.min.js"></script>
        </head>
        <body>
            <h2>{{story.title}}</h2>
            <div>
                <span class="voteCount">{{story.vote_count}}</span>  | <a href="javascript:VoteUp('{{story.key.id()}}');" >Vote Up Story</a>
            </div>
            <script>
                function VoteUp(storyKey){
                    $.ajax({
                      type: "POST",
                      url: "/vote/",
                      dataType: 'json',
                      data: JSON.stringify({ "storyKey": storyKey})
                    })
                    .done(function( data ) { // check why I use done
                        alert( "Vote Cast!!! Count is : " + data['story']['vote_count'] );
                        $('.voteCount').text(data['story']['vote_count']);
                    });
                };
            </script>
        </body>
    </html>
    

    组装,读起来很简单,然后运行。如果您需要一个有效的 git 示例,请发表评论。

    githublink(来自 cmets)

    【讨论】:

    • @haopei 对不起,我忘了你。给你github.com/jimmykane/gae-voting-ajax-example。我希望你给它加星 ;-)
    • 再次感谢@Jimmy Kane。
    • 你能简单解释一下 self.request.body 的作用吗?我在 webapp 和 appengine 文档上进行了搜索,但发现很少。文档中似乎几乎没有定义它。谢谢。
    • @haopei webapp-improved.appspot.com/guide/request.html 看看这个。它记录在那里......如果您需要更多帮助,请提及。
    • @haopei 日期时间属性不是 json 可序列化的。尝试像这样排除该属性:story.to_dict(exclude='my_datetime'),然后将其转换并附加到字典。在此处查看 to_dict 以及如何使用它 developers.google.com/appengine/docs/python/ndb/… 。日期时间也很痛苦。如果您需要进一步的帮助,请在此处再次提及,我将尝试添加日期时间序列化技术
    【解决方案2】:

    这是 GitHub 上的一个小 prototype 网络应用程序,用于测试如何使用 AJAX、Python 和 Google App Engine 处理 HTML 表单提交中的错误消息。它将为了解这三项技术如何融合在一起提供一个起点。你可以在https://ajax-prototype.appspot.com/上测试这个“应用程序”

    这是它在客户端的工作方式:

    • 这个htlm form submission被使用了:

      <form method="post" action="javascript:ajaxScript();">
      <label>Please pick a name</label>
      <input id="input" type="text">
      <input type="submit">
      <div id="error" style="color:red"></div>
      

    • 它会触发JavaScript functionajaxScript

      function ajaxScript() {
          var input = $("#input").val();
          $.ajax({
              type: "POST",
              url: "/",
              data: JSON.stringify({
                  "name": input
              }),
              dataType: "json"
          })
              .done(function(jsonResponse) {
                  $("#error").html(jsonResponse.message);
              });
      }
      
    • jQuery .ajax() 方法处理请求,而 .done() 方法最终将处理它从服务器获得的响应。

    在服务器端:

    • main.py 文件使用我们的 handler class AjaxHandler 处理业务的服务器端,它继承自 GAE 内置类 webapp2.RequestHandler

    • 在这个类中,post 方法处理 AJAX 请求:

      def post(self):
          data = json.loads(self.request.body)
          username = data["name"]
      
          if not re.match(r"^[a-zA-Z0-9_-]{3,20}$", username):
              if len(username) < 3:
                  message = "Your name must be at least 3 characters long."
              else:
                  message = "Allowed characters are \
                             a-z, A-Z, 0-9, underscores \
                             and hyphens."
          else:
              message = "Congrats!"
      
          self.response.write(json.dumps({"message": message}))
      
    • 基本上,方便的 json 模块提供了两个关键的 Python 成分

      • json.loads 处理浏览器发送到服务器的数据。
      • json.dumps 处理服务器响应浏览器请求发送的数据。
      • json.loadsself.request.body 参数是进程中唯一不太常见的 GAE 部分,因为它特定于任务。顾名思义,它从客户端发送的 Ajax 请求中获取正文。

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 2020-04-29
      • 2012-02-26
      • 2015-10-24
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2020-05-26
      • 2014-08-26
      相关资源
      最近更新 更多