haopei haopei - 7 days ago 6
Ajax Question

How to use AJAX with Google App Engine (Python)

I am completely novice at AJAX. I am familiar with HTML/CSS, jQuery and beginner at GAE and Python.

In an effort to understand how AJAX works, I would like to know how AJAX might be used (actual code) in this example below. Let's use a reddit-like example where vote ups/downs are ajaxified:

Here is the Story Kind:

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

The HTML would look like this:

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

How does AJAX fit inside here?


Ok Sir here we go... A simple app with one story and infinite votes... ;-)


application: anotherappname
version: 1
runtime: python27
api_version: 1
threadsafe: true

default_expiration: "0d 0h 5m"

- name: jinja2
  version: latest

- name: webapp2
  version: latest

- url: .*
  script: main.app


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):
    response.write('Oops! Naughty Mr. Jiggles (This is a 404)')

app.error_handlers[404] = handle_404


from google.appengine.ext import ndb

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


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}))

    def jinja_environment(self):
        jinja_environment = jinja2.Environment(
        return jinja_environment

class VoteHandler(webapp2.RequestHandler):
    def post(self):
        data = json.loads(self.request.body)
        story = ndb.Key(Story, data['storyKey']).get()
        story.vote_count += 1
        self.response.out.write(json.dumps(({'story': story.to_dict()})))

and finally


<!DOCTYPE html>
        <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>
            <span class="voteCount">{{story.vote_count}}</span>  | <a href="javascript:VoteUp('{{story.key.id()}}');" >Vote Up Story</a>
            function VoteUp(storyKey){
                  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'] );

Assemble, read it's simple enough and run. If you need a working git example just comment.

githublink (as from comments)