Created
May 10, 2014 13:15
-
-
Save guillaume86/c846f3be4a6d378749dd to your computer and use it in GitHub Desktop.
Edited https://github.com/davidedc/jsonp-db-redux to support CORS (allowing bigger payloads)
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
import inspect, operator | |
import urllib | |
import re | |
import logging | |
import webapp2 | |
import json | |
from google.appengine.ext import db | |
from google.appengine.api import users | |
from google.appengine.ext.webapp.util import run_wsgi_app | |
# only for cleanup mechanism | |
from datetime import datetime # strip for no auto cleanup | |
# The classes extending db.Model become | |
# "records" (or, properly, "entities") in the Datastore | |
# https://developers.google.com/appengine/docs/python/datastore/entities#Python_Kinds_and_identifiers | |
class LastCleaned(db.Model): # strip for no auto cleanup | |
lastCleaned = db.DateTimeProperty(auto_now=True) # strip for no auto cleanup | |
class EntitiesKinds(db.Model): | |
theKind = db.StringProperty() | |
def createEntity(className, jsonObj): | |
#if className[0] == "_": | |
# raise Exception("Class name must not start with _") | |
if className == "LastCleaned": # strip for no auto cleanup | |
raise Exception("LastCleaned is a reserved entity kind") # strip for no auto cleanup | |
#Return an empty instance if no jsonObj present | |
if jsonObj == None: | |
objClass = type(className,(db.Model,),{}) | |
return objClass() | |
if not type(jsonObj) == dict: | |
raise Exception("JSON object must start as a dictionary (as opposed to an array or string value)") | |
#Create entity | |
propertyDict = dict() | |
#If the property name has ".text" at the end, make it a text object | |
for k in jsonObj.keys(): | |
if len(str(k)) > 5 and str(k).rfind(".text") == len(str(k)) - 5: | |
propertyDict[str(k)] = db.TextProperty() | |
else: | |
propertyDict[str(k)] = db.StringProperty() | |
objClass = type(className,(db.Model,),propertyDict) | |
objEntity = objClass() | |
for k in jsonObj.keys(): | |
objEntity.__setattr__(str(k), json.dumps(jsonObj[k])) | |
return objEntity | |
class MainPage(webapp2.RequestHandler): | |
def get(self): | |
self.redirect("index.html") | |
class Put(webapp2.RequestHandler): | |
def get(self,className,jsonStr): | |
self.response.headers.add_header('Access-Control-Allow-Origin', '*') | |
logging.error('put being done') | |
logging.error('self.request.get: ' + self.request.get('callback')) | |
logging.error('keys: ' + str(self.request.GET.keys())) | |
logging.error('len: ' + str(len(self.request.GET.keys()))) | |
jsonObj = json.loads(jsonStr) | |
objEntity = createEntity(className, jsonObj) | |
theKey = str(objEntity.put()) | |
if self.request.get('callback'): | |
self.response.out.write(self.request.get('callback') + "(\"" + theKey + "\");") | |
else: | |
self.response.out.write(theKey ) | |
entityKind = EntitiesKinds(theKind = className) | |
v = EntitiesKinds.all().filter('theKind =', className) | |
if not v.get(): | |
entityKind = EntitiesKinds(theKind = className) | |
entityKind.put() | |
def post(self,className,_): | |
jsonStr = self.request.body | |
self.response.headers.add_header('Access-Control-Allow-Origin', '*') | |
logging.error('put being done') | |
logging.error('self.request.post: ' + self.request.get('callback')) | |
logging.error('keys: ' + str(self.request.POST.keys())) | |
logging.error('len: ' + str(len(self.request.POST.keys()))) | |
logging.error('body: ' + str(len(jsonStr))) | |
jsonObj = json.loads(jsonStr) | |
objEntity = createEntity(className, jsonObj) | |
theKey = str(objEntity.put()) | |
if self.request.get('callback'): | |
self.response.out.write(self.request.get('callback') + "(\"" + theKey + "\");") | |
else: | |
self.response.out.write(theKey ) | |
entityKind = EntitiesKinds(theKind = className) | |
v = EntitiesKinds.all().filter('theKind =', className) | |
if not v.get(): | |
entityKind = EntitiesKinds(theKind = className) | |
entityKind.put() | |
def options(self,className,_): | |
self.response.headers.add_header('Access-Control-Allow-Origin', '*') | |
self.response.headers.add_header('Access-Control-Allow-Headers', 'Origin, X-Requested-With, Content-Type, Accept') | |
self.response.headers.add_header('Access-Control-Allow-Methods', 'POST, GET') | |
class GetWithKey(webapp2.RequestHandler): | |
def get(self,keyStr): | |
self.response.headers.add_header('Access-Control-Allow-Origin', '*') | |
# the class name is encoded in the key string | |
# (in a non-cryptographically secure way) | |
# see https://developers.google.com/appengine/docs/python/datastore/keyclass?csw=1#Key_kind | |
className = str(db.Key(keyStr).kind()) | |
#Query for object based on a unique key | |
objClass = type(className, (db.Model,), {}) | |
ent = db.get(keyStr) | |
if ent: | |
objDict = dict() | |
for k in ent.__dict__["_entity"].keys(): | |
objDict[str(k)] = json.loads(ent.__dict__["_entity"][k]) | |
objectDump = json.dumps(objDict) | |
if self.request.get('callback'): | |
self.response.out.write(str(self.request.get('callback')) + "(" + objectDump + ");") | |
else: | |
self.response.out.write(objectDump) | |
class GetWithFilter(webapp2.RequestHandler): | |
def get(self,className): | |
self.response.headers.add_header('Access-Control-Allow-Origin', '*') | |
classString = str(self.request.get('filter') ) | |
logging.debug('filter: ' + classString) | |
if classString == '': | |
#Process get request for all objects of a type | |
objEntity = createEntity(className, None) | |
query = objEntity.all() | |
objArr = list() | |
for ent in query: | |
objDict = dict() | |
for k in ent.__dict__["_entity"].keys(): | |
objDict[str(k)] = json.loads(ent.__dict__["_entity"][k]) | |
objArr.append(objDict) | |
objectDump = json.dumps(objArr) | |
else: | |
jsonStr = urllib.unquote(classString) | |
jsonObj = json.loads(jsonStr) | |
objEntity = createEntity(className, jsonObj) | |
query = objEntity.all() | |
#Querying based on filtered information for an object | |
#Loop through the keys sent in the object and add query filters | |
for k in jsonObj.keys(): | |
query.filter(str(k) + " =", json.dumps(jsonObj.get(k))) | |
#Return results | |
objArr = list() | |
for ent in query: | |
objDict = dict() | |
for k in ent.__dict__["_entity"].keys(): | |
objDict[str(k)] = json.loads(ent.__dict__["_entity"][k]) | |
objArr.append(objDict) | |
objectDump = json.dumps(objArr) | |
if self.request.get('callback'): | |
self.response.out.write(str(self.request.get('callback')) + "(" + objectDump + ");") | |
else: | |
self.response.out.write(objectDump) | |
# strip this whole class for no auto cleanup | |
class WhenLastCleaned(webapp2.RequestHandler): | |
def get(self): | |
self.response.headers.add_header('Access-Control-Allow-Origin', '*') | |
logging.info('WhenLastCleaned()') | |
# just gets the first entity as there should be | |
# only one. all() only constructs the query | |
# fetching all entities. Get() then actually | |
# runs the query and fetches the first entity | |
# only. | |
ent = LastCleaned.all().get() | |
if ent != None: | |
# found a result in the DataStore | |
dateAndTimeAsString = str(ent.lastCleaned) | |
else: | |
dateAndTimeAsString = 'unknown' | |
objDict = dict() | |
objDict['resetTime'] = json.loads('"'+dateAndTimeAsString+'"') | |
objDict['currentTime'] = json.loads('"'+str(datetime.now())+'"') | |
self.response.out.write(str(self.request.get('callback')) + "(" + json.dumps(objDict) + ");") | |
return | |
# strip this whole class for no auto cleanup | |
class CleanAll(webapp2.RequestHandler): | |
def get(self): | |
self.response.headers.add_header('Access-Control-Allow-Origin', '*') | |
# this commented line below should | |
# delete all LastCleaned entities but, | |
# mysteriously, it doesn't, it leaves out | |
# some entities. The long-winded form | |
# below does the job instead. | |
# db.delete(LastCleaned.all(keys_only=True)) | |
query = LastCleaned.all(keys_only=True) | |
entries =query.fetch(1000) | |
db.delete(entries) | |
LastCleaned().put() | |
# first get all the kinds of the entities | |
allEntityKeys = EntitiesKinds.all() | |
# loop through the kinds and delete | |
# all entities of that kind | |
for entityKey in allEntityKeys: | |
theKind = str(entityKey.theKind) | |
objClass = type(theKind,(db.Model,),{}) | |
query = objClass.all(keys_only=True) | |
entries =query.fetch(1000) | |
db.delete(entries) | |
# finally delete the table with all the | |
# kinds | |
db.delete(allEntityKeys) | |
self.redirect("index.html") | |
application = webapp2.WSGIApplication( | |
[('/', MainPage), | |
(r'/put/buckets/([^/]*)/(.*)', Put), | |
(r'/get/keys/(.*)', GetWithKey), | |
(r'/get/buckets/([^/]*)/', GetWithFilter), | |
('/cleanAll', CleanAll), # strip for no auto cleanup | |
('/whenLastCleaned', WhenLastCleaned), # strip for no auto cleanup | |
], | |
debug=True) | |
def main(): | |
logging.debug('main()') | |
run_wsgi_app(application) | |
if __name__ == "__main__": | |
main() |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment