Quick tutorial
Introduction
This short tutorial shows the steps you need for creating the application "demo" distributed with the framework PyPaPi.
Defining the database with SQLAlchemy
In this example we use a small database SQLite, which is generated with the first execution of the pypapi-demo.py script.
The three tables (books/authors/genres) are defined in pypapidemo/db/model/tables.py.
from sqlalchemy import Column, Table, ForeignKeyConstraint
from sqlalchemy import UnicodeText, Integer
from pypapi.db.model.meta import metadata
genres = Table('genres', metadata,
Column('idgenre', Integer, primary_key=True),
Column('description', UnicodeText),
)
authors = Table('authors', metadata,
Column('idauthor', Integer, primary_key=True),
Column('name', UnicodeText),
Column('surname', UnicodeText),
)
books = Table('books', metadata,
Column('isbn', UnicodeText, primary_key=True),
Column('title', UnicodeText),
Column('idauthor', Integer),
Column('idgenre', Integer),
Column('description', UnicodeText),
ForeignKeyConstraint(['idauthor'], ['authors.idauthor']),
ForeignKeyConstraint(['idgenre'], ['genres.idgenre']),
)
Interfaces
The entities are modeled in our application corresponding to the tables in the database. Their interfaces are described in pypapidemo/db/interfaces.py.
from zope import schema
from zope.component.interface import provideInterface
from zope.component import provideUtility
from pypapi.db.field import DbObject
from pypapi.db.interfaces import IORM
from pypapi.db.interfaces.base import IEntitaBase
class IAuthor(IEntitaBase):
idauthor = schema.Int(title = u"ID author",
description = u"Unique ID")
name = schema.TextLine(title = u"Name",
description = u"Name")
surname = schema.TextLine(title = u"Surname",
description = u"Surname")
class IGenre(IEntitaBase):
idgenre = schema.Int(title = u"ID genre",
description = u"Unique ID")
description = schema.TextLine(title = u"Description",
description = u"Short description")
class IBook(IEntitaBase):
isbn = schema.TextLine(title = u"ISBN",
description = u"Isbn book code")
title = schema.TextLine(title = u"Title",
description = u"Book title")
author = DbObject(title = u"Author",
description = u"Book's author")
genre = DbObject(title = u"Genre",
description = u"Book's genre")
description = schema.TextLine(title = u"Description",
description = u"Short description")
for i in (IGenre, IAuthor, IBook,):
provideInterface('', i, IORM)
provideUtility(i, IORM, name=i.__name__)
Take a look that, while objects Author and Genre expose only properties related to scalar fields in the table, Book has two properties that express the relationship (foreign key in database) with author and genre.
Entities and mapping
There're three class entities that are implementing the three interfeces described above. These classes are inherited from the PyPaPi class EntitaBase. You can find their definition in pypapidemo/db/model/entities.py.
import zope.interface
from pypapi.db.model.entities.base import EntitaBase
from pypapidemo.db.interfaces import *
class Genre(EntitaBase):
zope.interface.implements(IGenre)
def getCaption(self):
return self.description
class Author(EntitaBase):
zope.interface.implements(IAuthor)
def getCaption(self):
return "%s %s" % (self.name, self.surname)
class Book(EntitaBase):
zope.interface.implements(IBook)
__all__ = ['Book', 'Author', 'Genre']
Thru the mapping defined in pypapidemo/db/model/mappers.py we can define the association between entities and master tables in database, and any eventual relational properties.
from sqlalchemy.orm import mapper, relationfrom pypapidemo.db.model import entities, tablesmapper(entities.Genre, tables.genres)mapper(entities.Author, tables.authors)mapper(entities.Book, tables.books,properties = {'author':relation(entities.Author),'genre':relation(entities.Genre),})
The Book form
The design of the form is delegated to Qt Designer, a form editor wich come with Qt SDK. (take a look to te note above)
Select "Main Window" from the templates/forms list in the startup form.
Then create the form using the widgets from the left widget box. ISBN and Title are QLineEdit, Author and Genre are PickerEntity, and Description is a QTextEdit.

You can bind widgets to the Book object's properties in this way:
For QLineEdit and QTextEdit you need to append a Dynamic Property named 'column' with value corresponding the Book's property that you want to bind (isbn, title, and description).
For the PickerEntity it's a little more difficult,. The Dynamic Properties are two: the first one is relative to the linked entity, and the other one to the lookup column to use to represent this entity. For the genre PickerEntity set entity='.genre' (notice the dot before genre) and caption='description"; for author entity='.author' and caption='caption'.
Note: you need to install the PyPaPi plugins in Qt Designer. Copy (or link) the contents of the folder lib/pypapi/ui/plugins in Qt Designer plugin folder (usualy Qt/plugins/designer/python/ in Qt install folder).
Config
There's a last step to accomplish, the configuration of the application. An PyPaPi application is usually builded from a couple of forms, and is configured in a zconfig file with extension 'conf'. Take a look at the file lib/pypapidemo/pypapidemo.conf (partially pasted above).
<database>
uri sqlite:///demo.db
</database>
<application>
modality mdi
title PyPaPi: demo
geometry 0,0,800,600
<form Books>
class pypapi.app.forms.PyPaPiForm
interface pypapidemo.db.interfaces.IBook
uifile ../../pypapidemo/app/books.ui
<entity .>
<column isbn/>
<column title/>
<column description/>
</entity>
<entity .author>
<column caption/>
</entity>
<entity .genre>
<column description/>
</entity>
</form>
</application>
The <database> tag define the access parameters to the database, while <application> is delegate to the config of some general parameters and the forms. For the Book form we define the controller class, the interface implemented from the objects our form is able to view and manage (IBook), and the file created with Qt Designer (uifile). Finally we describe the structure of the storage: the entity '.' is the root of the Book object, while the entities '. author' and '. genre' are those related.
Start
You can now execute the start script:
python pypapi-demo.py
If you don't specify a conf file thru the '-c' switch, the script search in the pypapidemo package a file named pypapidemo.conf.
And this is how the application appears: screenshot.
