|
 |
|
 |
| |
ZopeMag Links:
Home Page
About the Fish
Issue 09
Issue 08
Issue 07
Issue 06
Issue 05
Issue 04
Issue 03
Issue 02
Issue 01
Latest Issue
|
|
 |
|
 |
 |
|
|
 |
| |
|
|
| |
Letter from the Editor:
Welcome
Interviews:
In our first issue we interview the father of the Wiki and the inventor of Extreme Programming.
Ward Cunningham
Tutorials:
Throughout the quarter we cover topics of interest to Zope developers, designers, and users.
MetaFlow
Databases and ZPTs
Custom User Folders
Zope and CSS
Intranets
Product Review: Every two weeks we review a new Zope Product
Z Shrink
External File
DocumentLibrary
ZWiki
|
|
 |
|
 |
 |
|
|
 |
| |
|
|
| |
Downloads: Products we talk about in this issues Articles and Reviews
ZShrink
Zope Page Templates
LocalFS
SimpleZPTmyAdmin
Extended User Folder
MetaFlow
|
|
| |
|
|
|
|
 |
Databases and Zope Page Templates
Creating a Database User Interface with Zope Page Templates
- - - - - - - - - - - -
By Kristoph Kirchner | March 28, 2002
Getting Database Information
 |
The image on the right side shows the tree structure I used for the SimpleZPTmyAdmin site.
The DBs folder contains folders for each of the connected databases. In these folders are
the database connection associated with the respective database and any SQL methods that
might be needed by other applications to work with the database.
The first step was to get data about the connected databases for the navigation frame:
which databases exist and which tables are defined in each database. I tried using Python
scripts but, unfortunately, was told that I was ‘not allowed to access ZODBCDA in this
context’. Therefore, I switched to External Methods.
You cannot get data about a database directly through its connection. You must create a database
object using the connection string and call methods on the object that return the data you want.
The class DB should be defined in every database adapter (DA). I’ll show you below in an example
how to get the database object using the getDB_Tables(self, db) method. This method, as you
probably imagine, returns the tables defined in the database db.
Source Code of the getDB_Tables() method
1. from Products.ZODBCDA.db import DB
2. def getDB_Tables(self, db):
3. """ returns the tables of a db """
4. for i in self.DBs.aq_acquire(db).objectValues(['Z ODBC Database Connection']):
5. db_connection = i
6. conn_string = db_connection.connection_string
7. the_db = DB(conn_string)
8. db_tables=[]
9. for tab_tuple in the_db.table_info():
10. db_tables.append(tab_tuple[0])
11. return db_tables
The method needs the name of the folder in which to find the database connection
because it tries to call the objectValues() method of a folder in the DBs folder
(lines 4 and 5). After going through the folder, there should be a valid connection
object db_connection. Using its connection string (line 6), I created the database
object (line 7). The table_info() method of the DB class returns a list of tuples.
The first element of each tuple is the name of a table defined in the database.
Therefore, I created a list with just these names (lines 8-10), and returned that list.
The getDB_Tables(self, db) method is used in the left frame of the SimpleZPTmyAdmin
management screen. The frame’s output is created by the ZPT tabs_overview.html:
Partial Source Code of the ZPT tabs_overview.html
1. <div metal:fill-slot="main_content">
2. <a href="overview.html" target="main"><b>Home>/b<</a>
3. <div tal:repeat="db python:here.DBs.objectValues()">>
4. <h3>
5. <a href="" target="main" tal:attributes="href string:db_overview.html?db=${db/id}">>
6. <span tal:replace="db/title_or_id";content title or id<
7. </a>
8. </h3>
9. <div tal:repeat="tables python:here.getDBTables(db.getId())">
10. <a href="" tal:attributes="href string:tab_properties.html?db=${db/id}&tab=${tables}; target string:main" tal:content="tables">
11. </a>
12. </div>
13. </div>
14. </div>
In line 3, I use a tal:repeat construct to go through the objects of the DBs folder. That way I can access the folders’ properties and methods using the iterator db. For example, in line 6 I replace in each iteration the content of the span-tag with the current folder’s title or id (tal:replace=”db/title_or_id”). The tal:repeat is essentially the same as a dtml-in, but instead of sequence-item you define an iterator (e.g, db).
Line 6 creates a kind of header for each of the folders (i.e. the databases) in the DBs folder. I also want to show the tables within the databases – that’s where the getDB_Tables(self, db) method comes in. Thus, for each of the databases, I call the getDB_Tables(self, db) method via its External Method getDBTables(db) (line 9). Then I go through the returned list of tables and create a hyper link for each table (line 10). You can see the output of tabs_overview.html in the left frame in Figure 1 below.
A Sample ZPT – tab_properties.html
Now, let’s have a look at the ZPT tab_properties.html. Since all the ZPTs are similar in structure, I’ll use this one to show you the integration of macros, External Methods and plain TAL.
 |
Click on the image for a complete view |
You already know how the left frame of the figure above is created. The source code of the right frame in this figure comes from the tab_properties.html ZPT.
The first line is a headline which tells you which database and which table you are looking at and the specific Zope server you are working on. Since the name of the table, database and host change, depending upon which link in the left frame I clicked on, this headline has to be created dynamically. Perhaps you noticed earlier in this article when I was talking about getting the database information and the left frame, that the links contain variables that are sent to the page they lead to. These variables are the name of the database (db) and the table (tab) if the link is for a table (e.g, my_table), and just the name of the database if the link is for a database (e.g., First_DB).
After clicking one of the links in the left frame, these variables are added to the request so I can access them using the tal:content construct to create a dynamic headline on the following page (see first box in Figure 1).
Next, I wrote a method called getTabProperties(self, db, tab) which returns a table’s fields, their types, sizes and whether they may be empty or not. I used this method in a tal:repeat structure to create the table you see in Figure 1. Box 2 shows the tal:repeat structure as well as the code for one of the table rows. The method getTabProperties(self, db, tab) again uses a method of the DB class to get the fields of a table.
Since the query box appears in various pages, I decided to make it a macro. I created a ZPT called query_box.html with the form for the query box and defined the form as the macro query_box. Now, I can import this macro into any page, and whenever I have to make changes to the query box, I just need to do them in the ZPT query_box.html and any page that uses this macro will automatically change as well.
|
 |
|