This is installment two of the bizObject tutorial.  But before we can continue 
we need to setup two tables and add data to the tables.  I am providing 
standard “Postgres” SQL statements that will create the tables and insert the 
data we will be working with though out the tutorial.  However, each database 
engine has it own sightly different SQL syntax.  Therefore, pay close 
attention to fact that I have constraints on the tables and that both tables 
have primary keys.  The primary fields are auto-increment and I force the 
custno field to be unique using a constraint.   So if you are not using 
Postgres you will have to create your own SQL statements to setup the tables 
and enter the data.  We will not be using any store procedures/functions or 
anything else the database engine has available.  After all this is about 
Dabo and not Postgres.  However,  you can count on Dabo allowing your 
database to be all it can be!

-- drop table arcustomer;
CREATE TABLE arcustomer
(custno character varying(15) NOT NULL,
company character varying(35),
address1 character varying(35),
address2 character varying(35),
city character varying(35),
state character varying(2),
country character varying(60),
czip character varying(10),
pkid serial NOT NULL,
CONSTRAINT pk_arcust PRIMARY KEY (pkid),
CONSTRAINT arcustno UNIQUE (custno)
)
WITHOUT OIDS;
ALTER TABLE arcustomer OWNER TO johnf;
GRANT ALL ON TABLE arcustomer TO johnf;

--DROP TABLE contacts;

CREATE TABLE contacts
(
  custno character varying(15) NOT NULL,
  firstname character varying(20),
  lastname character varying(35),
  title character varying(20),
  phone character varying(15),
  email character varying(40),
  continent character varying(35),
  cont_note text,
  pkid serial NOT NULL,
  fk_arcust integer,
  CONSTRAINT pk_contact PRIMARY KEY (pkid)
)

WITHOUT OIDS;
ALTER TABLE contacts OWNER TO johnf;
GRANT ALL ON TABLE contacts TO johnf;

insert into arcustomer 
(custno,company,address1,address2,city,state,country,czip)
        values('AAA','AAA company', '123 Main 
St.','','Wooland','CA','USA','95776');
insert into arcustomer 
(custno,company,address1,address2,city,state,country,czip)
        values('BBB','BBB company', '123 East St.','Apt 
2','Wooland','CA','USA','95776');
insert into arcustomer 
(custno,company,address1,address2,city,state,country,czip)
        values('CCC','CCC company', '123 Walker 
St.','','Wooland','CA','USA','95776');
        
 insert into contacts 
(custno,firstname,lastname,title,phone,email,continent,fk_arcust)
      values('AAA', 'Ed', 'Leafe', 'Mr.', '','[EMAIL PROTECTED]','North 
America',1);
 insert into contacts 
(custno,firstname,lastname,title,phone,email,continent,fk_arcust)
      values('BBB', 'Paul', 'McNet', 'Mr.', '','[EMAIL PROTECTED]','North 
America',2);
 insert into contacts 
(custno,firstname,lastname,title,phone,email,continent,fk_arcust)
      values('CCC', 'Larry', 'Long', 'Mr.', '','[EMAIL PROTECTED]','North 
America',3);


OK we got the data into the tables.  Now we need to add a real bizObject to 
our form.  I like to think of myself as programmer (note: others might not 
agree with that label).  So I'm lazy!  Instead of typing the required code I 
use a short cut – ClassDesigner!  That's right, the guy (me) that hand codes 
the UI uses the ClassDesigner.  We are going to let ClassDesigner write our 
bizObject class code for us!

Open the ClassDesigner and right click on the form (window Title is “Dabo 
Class Designer”) and select the “Add Controls from Data environment”.  Select 
your connection file, and then select one of our tables (arcustomer or 
contacts).  Continue the process by selecting all the fields (click on Select 
all).  Click next. And continue to click next until you get to the “BizObj 
Code” screen and make sure you have checked the “Add BizObj Code”.  Then 
click on the “Finish” button.  Like magic the code we need will appear in 
the “ClassDesigner” editor.   Should look something like:

class PubliccontactsBizobj(dabo.biz.dBizobj):
                def afterInit(self):
                        self.DataSource = "public.contacts"
                        self.KeyField = "pkid"
                        self.addFrom("public.contacts")
                        self.addField("fk_arcust")
                        self.addField("firstname")
                        self.addField("title")
                        self.addField("pkid")
                        self.addField("lastname")
                        self.addField("cont_note")
                        self.addField("continent")
                        self.addField("phone")
                        self.addField("custno")
                        self.addField("email")
                        ...

The ClassDesigner has created a class, named the class and added all the 
fields in our table to the class.  Like I said - Magic.  I'm sure you are 
wondering what's up with the word “public” in "public.contacts".  Postgres 
has the concept of “schema” and Dabo of course supports schema's.  If you are 
not using Postgres and don't know anything about Postgres schema's don't 
worry about it.  If you followed my instructions the ClassDesigner will 
provide with the correct naming of the “DataSource”.

DataSource of course is the name of our table.  The “self.addFrom”  will 
normally match the DataSource and is used to provide the “from” in the SQL 
statement as in:
Select * “From public.contacts”.  And of course the “self.addField” statements 
add the names of the fields from our table.  But I skipped over 
the “self.Keyfield”?

“self.Keyfield” is the name of the primary field of the table.  Yes, Dabo 
supports compound keys.  There has been plenty of discussion on what Dabo 
should or should not do in support of primary keys.  If you are interested 
you can check out the Dabo list archive.  For the purposes of this tutorial 
we are using an auto-increment key provided by the database engine.  BTW with 
respect to Postgres users ALL tables are required to have a primary key.  
That fact is not because I was trying to force my ideas on Dabo users (I 
wrote most of the dbPostgres.py interface) although I believe all tables 
should have PK's.  It was because I could not find a way to provide table 
security based on user name without having a PK for each table.  We are 
building a one to many application and Dabo requires that a PK be provided so 
that the child relation can be maintained.  So if we want to use the power of 
Dabo we need PK's.

Next, ClassDesigner provided the code for an empty validator (is that a 
word?):
def validateRecord(self):
                """Returning anything other than an empty string from
                this method will prevent the data from being saved.
                """
                ret = ""
                # Add your business rules here. 
                return ret


Last, we have the code to create an instance of our bizObject class:
publiccontactsBizobj = PubliccontactsBizobj(self.Connection)
self.addBizobj(publiccontactsBizobj) 

OK so where do we put all this code?  Simple, the “class” is of course a 
class.  We add it to our code like any other class.  Below in our code I 
added the class at the top.  But where does the code to create the instance 
of class go?  In the “createBizobjs” method!  In Dabo the “app.start()” will 
execute the “createBizobjs” method and therefore create an instance of our 
class – create the object we will use.  A bizObject!

To add the second table I just repeat what I did to add the first table. 

Below I have created a small application.  I hate the UI in this example.  So 
would some kind reader post a better UI.  The code creates a one to many 
relation between a customer table and the customer contacts table.  I have 
added several buttons and extra lines to create the child relation and we 
will go over that code in the next installment.  So far all we have done is 
discuss the connection and added a bizObject to our code.  Next time we will 
discuss what steps I took to create the child relation and what Dabo provides 
to help the developer pass SQL statements to the database engine.

#!/usr/bin/env python
# -*- coding: utf-8 -*-
import os
import sys
import dabo
import dabo.dEvents as dEvents
import dabo.dException as dException
dabo.ui.loadUI('wx')
#the contact table
class PubliccontactsBizobj(dabo.biz.dBizobj):
        def afterInit(self):
                self.DataSource = "public.contacts"
                self.KeyField = "pkid"
                self.addFrom("public.contacts")
                self.addField("firstname")
                self.addField("phone")
                self.addField("pkid")
                self.addField("lastname")
                self.addField("title")
                self.addField("custno")
                self.addField("continent")
                self.addField("email")
                self.addField("cont_note")
                self.addField("fk_arcust")
                self.NonUpdateFields=["pkid"]
                self.LinkField = "fk_arcust"
                self.ParentLinkField ="pkid"
                self.FillLinkFromParent = True

        def validateRecord(self):
                """Returning anything other than an empty string from
                this method will prevent the data from being saved.
                """
                ret = ""
                # Add your business rules here. 
                return ret




#the customer table
class PublicarcustBizobj(dabo.biz.dBizobj):
        def afterInit(self):
                self.DataSource = "public.arcustomer"
                self.addFrom("public.arcustomer")
                self.KeyField = "pkid"
                self.addField("czip")
                self.addField("city")
                self.addField("pkid")
                self.addField("state")
                self.addField("company")
                self.addField("address1")
                self.addField("address2")
                self.addField("country")
                self.addField("custno")


def validateRecord(self):
        """Returning anything other than an empty string from
        this method will prevent the data from being saved.
        """
        ret = ""
        # Add your business rules here. 
        return ret

class CustomerPanel(dabo.ui.dPanel):
        def afterInit(self):
                self.Sizer=vs=dabo.ui.dSizer('h')
                gs = dabo.ui.dGridSizer(MaxCols=4,HGap=3, VGap=3)
                gs.append(dabo.ui.dLabel(self, Caption="Cust #"), 
halign="right")
                gs.append(dabo.ui.dTextBox(self, 
RegID="txtCustomerID",TextLength = 
10,DataSource ="public.arcustomer", DataField = "custno"), "expand", 
colSpan=3)
                gs.append(dabo.ui.dLabel(self, Caption="Address"), 
halign="right")
                gs.append(dabo.ui.dTextBox(self, RegID="txtAddress1",TextLength 
= 
35,DataSource ="public.arcustomer", DataField = "address1"), "expand", 
colSpan=3)
                gs.append(dabo.ui.dLabel(self, Caption=""), halign="right")
                gs.append(dabo.ui.dTextBox(self, RegID="txtAddress2",TextLength 
= 
35,DataSource ="public.arcustomert", DataField = "address2"), "expand", 
colSpan=3)
                gs.append(dabo.ui.dLabel(self, Caption="City"), halign="right")
                gs.append(dabo.ui.dTextBox(self, RegID="txtCity",DataSource 
="public.arcustomer", DataField = "city"), "expand", colSpan=3)
                gs.append(dabo.ui.dLabel(self, Caption="Country"), 
halign="right")
                gs.append(dabo.ui.dTextBox(self, RegID="txtCountry1",DataSource 
="public.arcust", DataField = "country"), "expand", colSpan=3)
                gs.append(dabo.ui.dLabel(self, Caption="State"), halign="right")
                gs.append(dabo.ui.dTextBox(self, 
RegID="txtSateID",ForceCase='upper',TextLength=2,DataSource 
="public.arcustomer", DataField = "state"))
                gs.append(dabo.ui.dLabel(self, Caption="Zip"), halign="right")
                gs.append(dabo.ui.dTextBox(self, 
RegID="txtZipD",TextLength=10,DataSource 
="public.arcustomer", DataField = "czip"), "expand")
                vs.append(gs,0,'x')
        

class ContactsPanel(dabo.ui.dPanel):
        def afterInit(self):
                self.Sizer = dabo.ui.dSizer("v")
                hs=dabo.ui.dSizer("h")
                contactGrid = 
dabo.ui.dGrid(self,RegID="contgridID",AlternateRowColoring 
=True,ColumnCount=6,SelectionMode = "Row",Editable = True,MovableColumns = 
False)
                
#self.contactGrid.bindEvent(dabo.dEvents.GridCellSelected,self.onGridCellSelected)
                contactGrid.DataSource = "public.contacts"
                contactGrid.Columns[0].Caption ="Title"
                contactGrid.Columns[0].DataField = "title"
                contactGrid.Columns[1].Caption ="First"
                contactGrid.Columns[1].DataField = "firstname"
                contactGrid.Columns[2].Caption ="Last"
                contactGrid.Columns[2].DataField = "lastname"
                contactGrid.Columns[3].Caption ="Email"
                contactGrid.Columns[3].DataField = "email"
                contactGrid.Columns[4].Caption ="Phone"
                contactGrid.Columns[4].DataField = "phone"
                contactGrid.Columns[5].Caption ="Continent"
                contactGrid.Columns[5].DataField = "continent"
                hs.append(contactGrid,1,'x')
                self.Sizer.append(hs,1,'x')


class MainForm(dabo.ui.dForm):
        def afterInit(self):
                self.Sizer=vs=dabo.ui.dSizer('v')
                custPanel=CustomerPanel(self)
                vs.append(custPanel,1,'x')
                vs.appendSpacer(8)
                hs= dabo.ui.dSizer('h')
                hs.append(dabo.ui.dButton(self, 
Caption="First",OnHit=self.first),0)
                hs.append(dabo.ui.dButton(self, 
Caption="Next",OnHit=self.next),0)
                hs.append(dabo.ui.dButton(self, 
Caption="Prior",OnHit=self.prior),0)     
                hs.append(dabo.ui.dButton(self, 
Caption="Last",OnHit=self.last),0)
                vs.append(hs)
                vs.appendSpacer(8)
                contPanel=ContactsPanel(self)
                vs.append(contPanel,2,'x')
                self.layout()
                self. requery()
                
                
        def first(self,evt):
                self.super()
        
        def next(self,evt):
                self.super()
                
        def prior(self,evt):
                self.super()
                
        def last(self,evt):
                self.super()
                
        def createBizobjs(self):
                self.Application.addConnectFile("tutorial.cnxml")
                self.Connection = 
self.Application.getConnectionByName("tutorial")
                
                publicarcustBizobj = PublicarcustBizobj(self.Connection)
                self.addBizobj(publicarcustBizobj)   
                
                publiccontactsBizobj = PubliccontactsBizobj(self.Connection)
                self.addBizobj(publiccontactsBizobj)
                publicarcustBizobj.addChild(publiccontactsBizobj)
                
                
if __name__ == "__main__":
        app = dabo.dApp()
        app.BasePrefKey = "bizObjTutor"
        app.setAppInfo("appName", "bizObject Tutorial ")
        app.MainFormClass = MainForm
        app.start()

As always if I have errors point them out.  Better yet provide the fix.
-- 
John Fabiani


_______________________________________________
Post Messages to: [email protected]
Subscription Maintenance: http://leafe.com/mailman/listinfo/dabo-users
Searchable Archives: http://leafe.com/archives/search/dabo-users
This message: http://leafe.com/archives/byMID/dabo-users/[EMAIL PROTECTED]

Reply via email to