Log in |
ZSQL Results How-ToThis how-to has been tested against Zope 2.5IntroductionSometimes is very useful to manipulate the result of a ZSQL method programmatically. While the internal mechanisms of Zope are the perfect tools for displaying and browsing the result, sometimes it is necessary to investigate deeply. This How-to provides a quick overview of the object returned by ZSQL methods, the Results object. I will assume that the reader has a basic knowledge in Zope, Python and SQL. If not, there are many documents on the Net that can explain more than me about these subjects. The Results classEvery time a ZSQL method is called, a Shared.DC.ZRDB.Results object is returned. This object contains various information which are quite interesting. Here is the list
Lets review those information in more detail. Playing with ZSQLHow to use ZSQL from DTML is very well documented, and therefore it is unuseful to repeat this here. Please see the Zope Book about this subject. What is really interesting for us is accessing the ZSQL method from scripts, or accessing their properties from DTML. Before we can try out some examples, we have to set up a little test environment (I do not like too theoretical things). What we need is:
Running the queryLet's run the query from a simple Python script. The script text should be as follows:
When we run it, we will be returned:
Pretty simple isn't it? As you can see, you are now able to inspect the field names returned from you ZSQL method. This is not that much useful as the data_dictionary. If we modify the program, we will have a clearer view of the table structure:
The result will be:
As you can see from the sample above, is now quite simple to inspect what the query returned and eventually react correctly. The dictionary contains many key:value pairs, where each key is the field name and each value is another dictionary containing the information about the field structure. If you know databases, this should not be a problem for you to understand. The next step is to retrieve the data from the Result object. As you may have already guessed it, they are contained in the abovementioned dictionaries list. Let's have a look at it:
The result is how you should expect it:
Each item in the list is a dictionary representing a record, therefore you can ask the Result object for how many records you have just by calling len(rec.dictionaries()). Using the Result objectNow we know how the Result object is made and how we can address it. There are many possible uses; depends what your application have to achieve. For instance, one of the normal SQL habits is to ask the database if a record exist for a given value. For instance, you want to write a method that returns true if the record exists, false if not. You need:
This script accepts one parameter called contactName. The body of the script will be:
Now it is easy to test if the record exist. You can of course make use of the <dtml-in><dtml-else> feature, but that feature you can't call it from Python, not as far as I know at least. Now the DTML method can look like:
<dtml-var standard_html_header> <dtml-if expr="isContact('vedovelli')"> if true...... <dtml-else> if false..... </dtml-if> <dtml-var standard_html_header>
Another Example (by David Hook)With the ability of accessing the ZSQL method programmatically, we can test test conditions like zero records. Here is how the routines were used .... python script: IsValidEmployee Sql Method: sqlSearch_Employee_Table
How it worksEmployee_Search is displayed to allow the user to enter an Employee Number. Once check is clicked, Employee_Result is displayed and passed the variable Employee_Number. Employee_Result uses IsValidEmployee(dtml-var Employee_Number) as the condtion for a dtml-if. The python script, IsValidEmployee(dtml-var Employee_Number) uses res= context.sqlSearch_Employee_Table to point to the results of the SQL method, sqlSearch_Employee_Table. len(res) gives the number of rows in the result table. This will be 1 if the Employee_Number exists or 0 if not. IsValidEmployee defaults to valid_employee=1 (The employee exists). If the test If len(res)==0 is true then valid_employee is set to 0 (Employee does not exist). The value of valid_Employee becomes the value returned by IsValidEmployee and tested in Employee_Results. Employee_Results then evaluates the dtml-if and displays the appropriate messages. A final noteIn this how-to, I have only scratched the surface. Therefore I please the reader to mail me for new ideas, clarifications and suggestion. They are more than welcome. |