#author:[email protected] import wsgiref.handlers from google.appengine.ext import webapp from rest import * class CommentResource(RestResource): def initialize(self): self.response.out.write("comment.initialize:format=%s
" %(self.format)) def index(self, entry_id): self.response.out.write("comment.index:entry_id=%s
" % entry_id) def show(self, id, entry_id): self.response.out.write("comment.show:id=%s,entry_id=%s
" %(id, entry_id)) def create(self, entry_id): self.response.out.write("comment.show:id=%s,entry_id=%s
" %(id, entry_id)) def update(self, id, entry_id): self.response.out.write("comment.update:id=%s,entry_id=%s
" %(id, entry_id)) def delete(self, id, entry_id): self.response.out.write("comment.delete:id=%s,entry_id=%s
" %(id, entry_id)) class EntryResource(RestResource): def initialize(self): self.response.out.write("entry.initialize:format=%s
" %(self.format)) def index(self): self.response.out.write("entry.index
") def show(self, id): self.response.out.write("entry.show:id=%s
" %(id)) def create(self): self.response.out.write("entry.show:id=%s
" %(id)) def update(self, id): self.response.out.write("entry.update:id=%s
" %(id)) def delete(self, id): self.response.out.write("entry.delete:id=%s
" %(id)) """""" def main(): RestHandler.route = { '/entries' : EntryResource, '/entries/:entry_id/comments' : CommentResource} application = webapp.WSGIApplication([(".*", RestHandler)], debug=True) wsgiref.handlers.CGIHandler().run(application) if __name__ == '__main__': main()
在这个rest实现机制中,资源支持的操作有5种,index,show,create,update,delete。
请求会根据请求的http method和路由设定自动和资源绑定。
比如
'/entries/:entry_id/comments' : CommentResource
这个路由说明 /entries/:entry_id/comments 这个模式的url将绑定到CommentResource上,
其中:entry_id是一个参数。
配置这个路由后,访问
/entries/2/comments 将调用CommentResource的index(self, entry_id)方法,里面的entry_id与路由配置的:entry_id是对应的,这里entry_id=2
同样
/entries/2/comments/1 将调用CommentResource的show(self, id, entry_id)方法,调用时候id=1,entry_id=2
该实现还支持不同的内容格式请求的区分,
/entries/2/comments/1
/entries/2/comments/1.html
/entries/2/comments/1.xml
这三个请求都将调用CommentResource的show(self, id, entry_id)方法,在这个方法中,可以通过self.format来获取用户所请求的格式,上面三个请求的内容格式分别为 html, html, xml
文件rest.py,实现url的解析及和资源的绑定
#author:[email protected] import wsgiref.handlers from google.appengine.ext import webapp _DEFAUT_RESOURCE_FORMAT = 'html' class RestResource: def __init__(self, request, response, params = {}, value = None, format = _DEFAUT_RESOURCE_FORMAT): self.request = request self.response = response self.params = params self.value = value self.format = format def initialize(self): """""" def index(self, *args): """""" def show(self, res, *args): """""" def create(self, *args): """""" def update(self, res, *args): """""" def delete(self, res, *args): """""" class RestHandler(webapp.RequestHandler): route = {} #{ # '/':IndexResource, # '/entries' : EntryResource, # '/entries/:entry_id/comments' : CommentResource} def __init__(self): self.resource = None def initialize(self, request, response): webapp.RequestHandler.initialize(self, request, response) if self.request.path == '' or self.request.path == '/': self.resource = RestHandler.route['/'](request, response) else: self.resource = RestHandler.get_rest_resource(request, response) if self.resource != None: self.resource.initialize() else: self.error(404) @staticmethod def get_rest_resource(request, response): path_fields = request.path[1:].split("/") resource = None resource_paramters = {} resource_value = None resource_format = _DEFAUT_RESOURCE_FORMAT for item in RestHandler.route.items(): resource = None resource_value = None resource_paramters.clear() resource_format = _DEFAUT_RESOURCE_FORMAT route_path = item[0][1:] route_path_fields = route_path.split("/") if len(route_path_fields) == len(path_fields) or len(route_path_fields) + 1 == len(path_fields): resource = item[1] for i in range(len(path_fields)): if i == len(path_fields) - 1 and path_fields[i].find(".") != -1: arr = path_fields[i].split('.') path_fields[i] = arr[0] resource_format = arr[1] if i == len(route_path_fields): resource_value = path_fields[i] elif path_fields[i] == route_path_fields[i]: continue elif route_path_fields[i].startswith(":"): resource_paramters[route_path_fields[i][1:]] = path_fields[i] else: resource = None break if resource != None: break; if resource == None: return None else: return resource(request, response, resource_paramters, resource_value, resource_format) def get(self): if self.resource != None: if self.resource.value != None: self.resource.show(self.resource.value, **self.resource.params) else: self.resource.index( **self.resource.params) def post(self): """Handler method for POST requests.""" if self.resource != None: if self.resource.value != None: self.resource.create( **self.resource.params) else: self.error(404) def put(self): if self.resource != None: if self.resource.value != None: self.resource.update(self.resource.vaue, **self.resource.params) else: self.error(404) def delete(self): if self.resource != None: if self.resource.value != None: self.resource.delete(self.resource.vaue, **self.resource.params) else: self.error(404)
完整代码见附件