changeset 2:61a3764cd5fb

new version RestDbInterface with working traversal and templates
author casties
date Fri, 21 May 2010 11:48:30 +0000
parents 48de7c260ffe
children 0e2d167d0983
files .project .pydevproject RestDbInterface.py __init__.py zpt/HTML_list_schemas.zpt zpt/HTML_list_tables.zpt zpt/HTML_table.zpt zpt/XML_list_schemas.zpt zpt/XML_list_tables.zpt zpt/XML_table.zpt zpt/addRestDbInterface.zpt
diffstat 11 files changed, 269 insertions(+), 4 deletions(-) [+]
line wrap: on
line diff
--- a/.project	Wed May 12 14:34:42 2010 +0000
+++ b/.project	Fri May 21 11:48:30 2010 +0000
@@ -3,6 +3,7 @@
 	<name>ChinaGisRestApi</name>
 	<comment></comment>
 	<projects>
+		<project>Zope 2.12</project>
 	</projects>
 	<buildSpec>
 		<buildCommand>
--- a/.pydevproject	Wed May 12 14:34:42 2010 +0000
+++ b/.pydevproject	Fri May 21 11:48:30 2010 +0000
@@ -5,7 +5,5 @@
 
 <pydev_property name="org.python.pydev.PYTHON_PROJECT_VERSION">python 2.6</pydev_property>
 <pydev_property name="org.python.pydev.PYTHON_PROJECT_INTERPRETER">Default</pydev_property>
-<pydev_pathproperty name="org.python.pydev.PROJECT_SOURCE_PATH">
-<path>/ChinaGisRestApi/src</path>
-</pydev_pathproperty>
+
 </pydev_project>
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/RestDbInterface.py	Fri May 21 11:48:30 2010 +0000
@@ -0,0 +1,168 @@
+'''
+Created on 19.5.2010
+
+@author: casties
+'''
+
+from OFS.Folder import Folder
+from Products.PageTemplates.PageTemplateFile import PageTemplateFile
+from Products.ZSQLExtend import ZSQLExtend
+import logging
+
+from zope.interface import implements
+from zope.publisher.interfaces import IPublishTraverse
+from ZPublisher.BaseRequest import DefaultPublishTraverse
+#from zope.publisher.interfaces import NotFound 
+#from zope.app import zapi 
+#from zope.component import queryMultiAdapter
+
+
+class RestDbInterface(Folder):
+    """Object for RESTful database queries
+    path schema: /[XML,JSON,HTML]/{schema}/{table}/
+    omitting table gives a list of schemas
+    omitting table and schema gives a list of schemas 
+    """
+    implements(IPublishTraverse)
+    
+    meta_type="RESTdb"
+
+    # data templates
+    XML_list_schemas = PageTemplateFile('zpt/XML_list_schemas', globals())
+    XML_list_tables = PageTemplateFile('zpt/XML_list_tables', globals())
+    XML_table = PageTemplateFile('zpt/XML_table', globals())
+    HTML_list_schemas = PageTemplateFile('zpt/HTML_list_schemas', globals())
+    HTML_list_tables = PageTemplateFile('zpt/HTML_list_tables', globals())
+    HTML_table = PageTemplateFile('zpt/HTML_table', globals())
+
+    
+    
+    def __init__(self, id, title):
+        """init"""
+        self.id = id
+        self.title = title
+        # create template folder
+        self.manage_addFolder('template')
+
+    
+    def publishTraverse(self,request,name):
+        """change the traversal"""
+        # get stored path
+        path = request.get('restdb_path', [])
+        logging.debug("publishtraverse: name=%s restdb_path=%s"%(name,path))
+        
+        if name == "index_html":
+            # end of traversal
+            return self.index_html
+            #TODO: should we check more?
+        else:
+            # traverse
+            if len(path) == 0:
+                # first segment
+                if name in ['XML','JSON','HTML']:
+                    # virtual path -- continue traversing
+                    path = [name]
+                    request['restdb_path'] = path
+                else:
+                    # try real path
+                    tr = DefaultPublishTraverse(self, request)
+                    ob = tr.publishTraverse(request, name)
+                    return ob
+            else:
+                path.append(name)
+
+        # continue traversing
+        return self
+ 
+    def index_html(self,REQUEST,RESPONSE):
+        """index method"""
+        path = REQUEST.get('restdb_path',[])
+        logging.debug("index_html path=%s"%path)
+        if len(path) == 1:
+            # list of schemas
+            return self.showListOfSchemas(format=path[0])
+        elif len(path) == 2:
+            # list of tables
+            return self.showListOfTables(format=path[0],schema=path[1])
+        elif len(path) == 3:
+            # table
+            return self.showTable(format=path[0],schema=path[1],table=path[2])
+        
+        # don't know what to do
+        return str(REQUEST)
+
+ 
+    def showTable(self,format='XML',schema='public',table=None):
+        """returns PageTemplate with tables"""
+        logging.debug("showtable")
+        pt = getattr(self.template, '%s_table'%format, None)
+        if pt is None:
+            return "ERROR!! template %s_table not found"%format
+        
+        data = self.getTable(schema,table)
+        return pt(data=data,tablename=table)
+ 
+ 
+    def getTable(self,schema='public',table=None,username='guest'):
+        """return table data"""
+        logging.debug("gettable")
+        qstr="select * from %s"%table
+        data=self.ZSQLSimpleSearch(qstr)
+        return data
+
+    def showListOfTables(self,format='XML',schema='public'):
+        """returns PageTemplate with list of tables"""
+        logging.debug("showlistoftables")
+        pt = getattr(self.template, '%s_list_tables'%format, None)
+        if pt is None:
+            return "ERROR!! template %s_list_tables not found"%format
+        
+        data = self.getListOfTables(schema)
+        return pt(data=data,schema=schema)
+ 
+    def getListOfTables(self,schema='public',username='guest'):
+        """return list of tables"""
+        logging.debug("getlistoftables")
+        # get list of fields and types of db table
+        qstr="""select c.relname FROM pg_catalog.pg_class c
+            LEFT JOIN pg_catalog.pg_namespace n ON n.oid = c.relnamespace
+            WHERE c.relkind IN ('r','') AND n.nspname NOT IN ('pg_catalog', 'pg_toast')
+            AND pg_catalog.pg_table_is_visible(c.oid)"""
+        #qstr="select attname, format_type(pg_attribute.atttypid, pg_attribute.atttypmod) from pg_attribute, pg_class where attrelid = pg_class.oid and pg_attribute.attnum > 0"
+        data=self.ZSQLSimpleSearch(qstr)
+        return data
+
+    def showListOfSchemas(self,format='XML'):
+        """returns PageTemplate with list of schemas"""
+        logging.debug("showlistofschemas")
+        pt = getattr(self.template, '%s_list_schemas'%format, None)
+        if pt is None:
+            return "ERROR!! template %s_list_schemas not found"%format
+        
+        data = self.getListOfSchemas()
+        return pt(data=data)
+ 
+    def getListOfSchemas(self,username='guest'):
+        """return list of schemas"""
+        logging.debug("getlistofschemas")
+        # TODO: really look up schemas
+        data=['public']
+        return data
+
+        
+        
+manage_addRestDbInterfaceForm=PageTemplateFile('zpt/addRestDbInterface',globals())
+
+def manage_addRestDbInterface(self, id, title='', label='', description='',
+                     createPublic=0,
+                     createUserF=0,
+                     REQUEST=None):
+        """Add a new object with id *id*."""
+    
+        ob=RestDbInterface(str(id),title)
+        self._setObject(id, ob)
+        
+        #checkPermission=getSecurityManager().checkPermission
+        REQUEST.RESPONSE.redirect('manage_main')
+
+        
\ No newline at end of file
--- a/__init__.py	Wed May 12 14:34:42 2010 +0000
+++ b/__init__.py	Fri May 21 11:48:30 2010 +0000
@@ -1,5 +1,6 @@
 
-import REST_test 
+import REST_test
+import RestDbInterface
 
 #class RESTinterface(DefaultPublishTraverse):
 #    """VLP spezifische Erweiterung der Collection"""
@@ -28,3 +29,11 @@
           REST_test.manage_addRESTclass
           )
         )
+
+    context.registerClass(
+         RestDbInterface.RestDbInterface,
+        constructors = (
+          RestDbInterface.manage_addRestDbInterfaceForm,
+          RestDbInterface.manage_addRestDbInterface
+          )
+        )
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/zpt/HTML_list_schemas.zpt	Fri May 21 11:48:30 2010 +0000
@@ -0,0 +1,21 @@
+<html tal:define="format python:request.get('format','table')">
+  <head>
+    <title tal:content="template/title">The title</title>
+    <meta http-equiv="content-type" content="text/html;charset=utf-8">
+  </head>
+  <body>
+    <h2>List of schemas</h2>
+    <tal:block tal:condition="python:format=='select'">
+    <select id="schemas">
+      <option tal:repeat="sch options/data" tal:content="sch"/>
+    </select>
+    </tal:block>
+    <tal:block tal:condition="python:format=='table'">
+    <table id="schemas">
+      <tr tal:repeat="sch options/data">
+	<td><a tal:attributes="href sch" tal:content="sch"/></td>
+      </tr>
+    </table>
+    </tal:block>
+  </body>
+</html>
\ No newline at end of file
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/zpt/HTML_list_tables.zpt	Fri May 21 11:48:30 2010 +0000
@@ -0,0 +1,21 @@
+<html tal:define="format python:request.get('format','table')">
+  <head>
+    <title tal:content="template/title">The title</title>
+    <meta http-equiv="content-type" content="text/html;charset=utf-8">
+  </head>
+  <body>
+    <h2>List of tables for schema <span tal:replace="options/schema"/></h2>
+    <tal:block tal:condition="python:format=='select'">
+    <select id="tables">
+      <option tal:repeat="tbl options/data" tal:content="tbl/relname"/>
+    </select>
+    </tal:block>
+    <tal:block tal:condition="python:format=='table'">
+    <table id="tables">
+      <tr tal:repeat="tbl options/data">
+	<td><a tal:attributes="href tbl/relname" tal:content="tbl/relname"/></td>
+      </tr>
+    </table>
+    </tal:block>
+  </body>
+</html>
\ No newline at end of file
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/zpt/HTML_table.zpt	Fri May 21 11:48:30 2010 +0000
@@ -0,0 +1,19 @@
+<html tal:define="format python:request.get('format','table'); fields options/data/names">
+  <head>
+    <title tal:content="template/title">The title</title>
+    <meta http-equiv="content-type" content="text/html;charset=utf-8">
+  </head>
+  <body>
+    <h2>table <span tal:replace="options/tablename"/></h2>
+    <tal:block tal:condition="python:format=='table'">
+    <table id="table">
+      <tr>
+	<th tal:repeat="field fields" tal:content="field"/>
+      </tr>
+      <tr tal:repeat="row options/data">
+	<td tal:repeat="field fields" tal:content="python:row[field]"/>
+      </tr>
+    </table>
+    </tal:block>
+  </body>
+</html>
\ No newline at end of file
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/zpt/XML_list_schemas.zpt	Fri May 21 11:48:30 2010 +0000
@@ -0,0 +1,6 @@
+<?xml version="1.0" encoding="utf-8"?>
+<schemalist xmlns:tal="http://xml.zope.org/namespaces/tal">
+  <schema tal:repeat="sch options/data">
+	<name tal:content="sch"/>
+  </schema>
+</schemalist>
\ No newline at end of file
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/zpt/XML_list_tables.zpt	Fri May 21 11:48:30 2010 +0000
@@ -0,0 +1,6 @@
+<?xml version="1.0" encoding="utf-8"?>
+<tablelist xmlns:tal="http://xml.zope.org/namespaces/tal">
+  <table tal:repeat="tbl options/data">
+	<name tal:content="tbl/relname"/>
+  </table>
+</tablelist>
\ No newline at end of file
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/zpt/XML_table.zpt	Fri May 21 11:48:30 2010 +0000
@@ -0,0 +1,7 @@
+<?xml version="1.0" encoding="utf-8"?>
+<table xmlns:tal="http://xml.zope.org/namespaces/tal" 
+  tal:define="fields options/data/names" tal:attributes="name options/tablename">
+  <row tal:repeat="row options/data">
+	<column tal:repeat="field fields" tal:attributes="name field" tal:content="python:row[field]"/>
+  </row>
+</table>
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/zpt/addRestDbInterface.zpt	Fri May 21 11:48:30 2010 +0000
@@ -0,0 +1,9 @@
+  <div tal:replace="structure here/manage_page_header">Header</div>
+  <h2>Add a RESTclass</h2>
+  <form method="post" action="manage_addRestDbInterface">
+    <p class="form-label">ID</p>
+        <p class="form-element"><input size="80" name="id"/></p>
+    <p class="form-label">Title</p>
+        <p class="form-element"><input size="80" name="title"/></p>
+     <p><input type="submit" value="Add" /></p>
+  </form>