Revision: 31703
Initial Code
Initial URL
Initial Description
Initial Title
Initial Tags
Initial Language
at September 10, 2010 23:35 by morningcatmedia
Initial Code
# Four files
# app.yaml
# Index.html
# Base.html
# helloworld.py
# app.yaml
application: helloworld
version: 1
runtime: python
api_version: 1
handlers:
- url: /static
static_dir: static
- url: /stylesheets
static_dir: stylesheets
- url: /.*
script: helloworld.py
# Index.html This is the Django template
{% extends "base.html" %}
{% block main %}
<div><input type="submit" onclick="onAddSuccess()" value="List Guestbook"></div>
{% endblock %}
{% block form %}
{% if logged %}
<form action="/sign" enctype="multipart/form-data" method="post">
<div><textarea id="content" name="content" rows="3" cols="60"></textarea></div>
{% for type_val in type %}
<div><input type="radio" name="type" value="{{type_val}}">{{type_val}}</div>
{% endfor %}
<input type="file" name="img" id="img" >
<div><input type="submit" value="Sign Guestbook"></div>
</form>
{% endif %}
<a href="{{ url }}">{{ url_linktext }}</a>
{% endblock %}
######################################
# Below is base.html
<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN"
"http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
<html>
<head>
<link type="text/css" rel="stylesheet" href="/stylesheets/main.css" />
<script type="text/javascript" src="./static/json.js"></script>
<script type="text/javascript">
//
// As mentioned at http://en.wikipedia.org/wiki/XMLHttpRequest
//
if( !window.XMLHttpRequest ) XMLHttpRequest = function()
{
try{ return new ActiveXObject("Msxml2.XMLHTTP.6.0") }catch(e){}
try{ return new ActiveXObject("Msxml2.XMLHTTP.3.0") }catch(e){}
try{ return new ActiveXObject("Msxml2.XMLHTTP") }catch(e){}
try{ return new ActiveXObject("Microsoft.XMLHTTP") }catch(e){}
throw new Error("Could not find an XMLHttpRequest alternative.")
};
//
// Makes an AJAX request to a local server function w/ optional arguments
//
// functionName: the name of the server's AJAX function to call
// opt_argv: an Array of arguments for the AJAX function
//
function GetRequest(function_name, opt_argv) {
// If optional arguments was not provided, create it as empty
if (!opt_argv)
opt_argv = new Array();
// Find if the last arg is a callback function; save it
var callback = null;
var len = opt_argv.length;
if (len > 0 && typeof opt_argv[len-1] == 'function') {
callback = opt_argv[len-1];
opt_argv.length--;
}
var async = (callback != null);
// Encode the arguments in to a URI
var query = 'action=' + encodeURIComponent(function_name);
for (var i = 0; i < opt_argv.length; i++) {
var key = 'arg' + i;
var val = JSON.stringify(opt_argv[i]);
query += '&' + key + '=' + encodeURIComponent(val);
}
query += '&time=' + new Date().getTime(); // IE cache workaround
// See http://en.wikipedia.org/wiki/XMLHttpRequest to make this cross-browser compatible
var req = new XMLHttpRequest();
// Create a 'GET' request w/ an optional callback handler
req.open('GET', '/list?' + query, async);
//req.open('GET', '/list', async);
if (async) {
req.onreadystatechange = function() {
if(req.readyState == 4 && req.status == 200) {
var response = null;
try {
response = JSON.parse(req.responseText);
} catch (e) {
response = req.responseText;
}
callback(response);
}
}
}
// Make the actual request
req.send(null);
}
function PostRequest(function_name, opt_argv) {
if (!opt_argv)
opt_argv = new Array();
// Find if the last arg is a callback function; save it
var callback = null;
var len = opt_argv.length;
if (len > 0 && typeof opt_argv[len-1] == 'function') {
callback = opt_argv[len-1];
opt_argv.length--;
}
var async = (callback != null);
// Build an Array of parameters, w/ function_name being the first parameter
var params = new Array(function_name);
for (var i = 0; i < opt_argv.length; i++) {
params.push(opt_argv[i]);
}
var body = JSON.stringify(params);
// Create an XMLHttpRequest 'POST' request w/ an optional callback handler
var req = new XMLHttpRequest();
req.open('POST', '/rpc', async);
req.setRequestHeader("Content-type", "application/x-www-form-urlencoded");
req.setRequestHeader("Content-length", body.length);
req.setRequestHeader("Connection", "close");
if (async) {
req.onreadystatechange = function() {
if(req.readyState == 4 && req.status == 200) {
var response = null;
try {
response = JSON.parse(req.responseText);
} catch (e) {
response = req.responseText;
}
callback(response);
}
}
}
// Make the actual request
req.send(body);
}
// Adds a stub function that will pass the arguments to the AJAX call
function InstallPostFunction(obj, functionName) {
obj[functionName] = function() { PostRequest(functionName, arguments); }
}
// Adds a stub function that will pass the arguments to the AJAX call
function InstallGetFunction(obj, functionName) {
obj[functionName] = function() { GetRequest(functionName, arguments); }
}
</script>
<script type="text/javascript">
// Server object that will contain the callable methods
var server = {};
var newsrv = {};
// Insert 'Add' as the name of a callable method
// Add will add the record to the database
InstallPostFunction(server, 'Add');
InstallGetFunction(newsrv, 'list');
// Handy "macro"
function $(id){
return document.getElementById(id);
}
// Client function that calls a server rpc and provides a callback
// For this application, doAdd will Post the entry
function doAdd() {
server.Add($('content').value, $('img').value, onAddSuccess);
}
// Callback for after a successful doAdd
function onAddSuccess() {
newsrv.list($('content').value, $('img').value,onGetSuccess);
}
function onGetSuccess(newresponse) {
document.getElementById('result').innerHTML = newresponse;
}
</script>
</head>
<body onLoad="onAddSuccess()">
<div>
{% block form %}
{% endblock %}
</div>
<div>
{% block main %}
{% endblock %}
</div>
<div id="result">
</div>
</body>
</html>
######################################
# Below is helloworld.py
import cgi
import os
import datetime
import logging
from google.appengine.api import users
from google.appengine.ext import webapp
from google.appengine.ext.webapp.util import run_wsgi_app
from google.appengine.ext import db
from google.appengine.ext.webapp import template
from google.appengine.api import images
from google.appengine.api import memcache
from django.utils import simplejson
class Greeting(db.Model):
author = db.UserProperty()
content = db.StringProperty(multiline=True)
date = db.DateTimeProperty(auto_now_add=True)
type = db.StringProperty(indexed=False)
avatar = db.BlobProperty(default=None)
usremail = db.EmailProperty()
class MainPage(webapp.RequestHandler):
def get(self):
self.render_form()
stats = memcache.get_stats()
#self.response.out.write("<b>Cache Hits:%s</b><br>" % stats['hits'])
#self.response.out.write("<b>Cache Misses:%s</b><br><br>" % stats['misses'])
def render_form(self):
greetings_query = Greeting.all().order('-date')
#greetings_query=db.GqlQuery("SELECT * FROM Greeting WHERE content >= :1 AND content < :2", "ccc", u"abc" + u"\ufffd")
greetings = greetings_query.fetch(10)
type = set(["cat", "dog", "bird"])
logged = False
if users.get_current_user():
logged = True
url = users.create_logout_url(self.request.uri)
url_linktext = 'Logout'
else:
logged = False
url = users.create_login_url(self.request.uri)
url_linktext = 'Login to comment'
template_values = {
'greetings': greetings,
'url': url,
'url_linktext': url_linktext,
'logged': logged,
}
path = os.path.join(os.path.dirname(__file__), 'index.html')
self.response.out.write(template.render(path, template_values))
class Guestbook(webapp.RequestHandler):
def post(self, *args):
greeting = Greeting()
if users.get_current_user():
greeting.author = users.get_current_user()
greeting.content = self.request.get('content')
greeting.type = self.request.get('type')
if self.request.get('img'):
picture = self.request.get('img')
avatar = images.resize(self.request.get("img"), 32, 32)
greeting.avatar = db.Blob(avatar)
greeting.put()
self.redirect('/')
def get(self):
# Here we need to put the memcache call
# greetings = memcache.get("greetings")
# if greetings is not None:
# return greetings
# else:
greetings_query = Greeting.all().order('-date')
#greetings_query=db.GqlQuery("SELECT * FROM Greeting WHERE content >= :1 AND content < :2", "ccc", u"abc" + u"\ufffd")
greetings = greetings_query.fetch(10)
logged = False
if users.get_current_user():
logged = True
url = users.create_logout_url(self.request.uri)
url_linktext = 'Logout'
else:
logged = False
url = users.create_login_url(self.request.uri)
url_linktext = 'Login to comment'
for greeting in greetings:
self.response.out.write("<p>")
self.response.out.write(greeting.content)
#self.response.out.write(greeting.avatar)
self.response.out.write('<img src=http://localhost:8080/img?img_id='+str(greeting.key())+' </img>')
self.response.out.write("</p>")
class Image (webapp.RequestHandler):
def get(self):
greeting = db.get(self.request.get("img_id"))
if greeting.avatar:
self.response.headers['Content-Type'] = "image/png"
self.response.out.write(greeting.avatar)
else:
self.response.out.write("No image")
#RPC Functions
class RPCHandler(webapp.RequestHandler):
""" Allows the functions defined in the RPCMethods class to be RPCed."""
def __init__(self):
webapp.RequestHandler.__init__(self)
self.methods = RPCMethods()
def post(self, *args):
args = simplejson.loads(self.request.body)
func, args = args[0], args[1:]
if func[0] == '_':
self.error(403) # access denied
return
func = getattr(self.methods, func, None)
if not func:
self.error(404) # file not found
return
result = func(*args)
self.response.out.write(simplejson.dumps(result))
def get(self):
func = None
action = self.request.get('action')
if action:
if action[0] == '_':
self.error(403) # access denied
return
else:
func = getattr(self.methods, action, None)
if not func:
self.error(404) # file not found
return
args = ()
while True:
key = 'arg%d' % len(args)
val = self.request.get(key)
if val:
args += (simplejson.loads(val),)
else:
break
result = func(*args)
self.response.out.write(simplejson.dumps(result))
class RPCMethods():
""" Defines the methods that can be RPCed.
NOTE: Do not allow remote callers access to private/protected "_*" methods.
"""
def Add(self, *args):
greeting = Greeting()
greeting.content = args[0]
#Can't do this since I need upload the image via ajax, and that's not allowed.
#greeting.avatar = args[1]
greeting.put()
return True
#**********
def main():
application = webapp.WSGIApplication(
[('/', MainPage),
('/img',Image),
('/rpc', RPCHandler),
('/list',Guestbook),
('/sign',Guestbook),
],
debug=True)
run_wsgi_app(application)
if __name__ == "__main__":
main()
Initial URL
Initial Description
Initial Title
Google App Ajax Post Comment
Initial Tags
ajax, google
Initial Language
Python