Karrigell/Managing The Database
Database engine
editKarrigell can use any database engine (MySQL, SQLite, etc) using the appropriate module. For this example we will use a very simple module that stores the data we need : for each CD in the collection, the artist name and the title of the album
Copy this in a module called simpledb.py :
def read(filename): records = [] try: for line in open(filename): records.append(line.strip().split("#")) except IOError: pass return records def save(records,filename): out = open(filename,'w') for items in records: out.write('#'.join(items)+'\n') out.close()
When you import the module in a script you simply use its functions read() and save(). The information is stored in a list of tuples
For our CD collection application, the information will consist in only 2 values : the artist name and the CD title. If we call the database file mycds.db the code to print all the CDs in an HTML table will simply be :
simpledb = Import('simpledb') cds = simpledb.read('mycds.db') for (artist,title) in cds: print artist,title
Notice the way you import the module simpledb.py : you can't use the usual import statement, because in a shared environment like a web server, there are issues with the resolution of module names to files in the file system. Karrigell uses a built-in function Import(module_url) for user-defined modules ; for the modules in the standard Python distribution, you can safely use import
Home page with the CD list
editWe can now modify the index() function to print the list of CDs:
simpledb = Import('simpledb') def index(): print "<h1>My record collection</h1>" # login / logout logged = hasattr(Session(),"user") and Session().user is not None if logged: print 'Logged in as %s<br>' %Session().user print '<a href="logout">Logout</a><p>' else: print '<a href="login">Login</a><p>' # print existing records cds = simpledb.read('mycds.db') if cds: print '<table border="1">' print '<tr><th>Artist</th><th>Title</th></tr>' for (artist,title) in cds: print '<tr><td>%s</td><td>%s</td></tr>' %(artist, title) print '</table><p>' else: print "No CD in the collection<p>" # prompt logged in users to enter a new record if logged: print '<a href="new_cd">Enter new CD</a><p>' # page counter Include('../counter.py',counter_file='counter.txt')
Notice that simpledb is imported at the module level, not inside the function index() : the names defined at module level are available in the functions, exactly like in ordinary Python scripts
Adding new CDs
editFor logged-in users there is a link to enter new CDs in the database. The href attribute of this link is new_cd, so we must write a function new_cd()
This function will print a form to enter the CD artist and title, and submit the data to another function which will actually write the information in the database, then return to the home page
At this stage you shouldn't have problems to understand the code below :
def new_cd(): print '<h1>New CD</h1>' print '<form action="insert_new_cd" method="post">' print 'Artist <input name="artist"><br>' print 'Title <input name="title"><br>' print '<input type="submit" value="Ok">' print '</form>' def insert_new_cd(artist,title): cds = simpledb.read('mycds.db') cds.append((artist,title)) simpledb.save(cds,'mycds.db') raise HTTP_REDIRECTION,"index"
Add these functions to index.ks and enter a couple of CDs in the database. Each time you are back to the home page you should see the collection growing
Editing records
editLogged-in users should be able to edit the information about a CD : on the list they should see a link "Edit" sending them to a page where the information will be available for editing
This requires that the information about the CD is carried from the home page to the edition page. For this we could append the information about the CD (artist + title) to the link, for instance : href = edit?artist=Beatles&title=Revolver ; but database engines usually provide record identifiers, that is, integers which identify the record
In our simple database we can use the index of the item in the list as identifier, so that we can rewrite the code to print the CD collection this way :
# print existing records simple db = Import('simpledb') cds = simpledb.read('mycds.db') if cds: print '<table border="1">' print '<tr><th>Artist</th><th>Title</th></tr>' for num,(artist,title) in enumerate(cds): print '<tr><td>%s</td><td>%s</td>' %(artist, title) if logged: print '<td><a href="edit?num=%s">Edit</a></td>' %num print '</tr>' print '</table><p>' else: print "No CD in the collection<p>"
The function edit() will receive one argument called num. All arguments passed to functions in Karrigell Services are bytestrings, so before using this argument num as the index in a list don't forget to convert it to an integer
def edit(num): cds = simpledb.read('mycds.db') artist,title = cds[int(num)] print '<h1>New CD</h1>' print '<form action="update_cd" method="post">' print '<input name="num" type="hidden" value="%s">' %num print 'Artist <input name="artist" value="%s"><br>' %artist print 'Title <input name="title" value="%s"><br>' %title print '<input type="submit" value="Ok">' print '</form>' def update_cd(num,artist,title): cds = simpledb.read('mycds.db') cds[int(num)] = (artist,title) simpledb.save(cds,'mycds.db') raise HTTP_REDIRECTION,"index"
Removing records
editThe final step is to enable deletion of CDs from the base : once again, edit the function index() like this
# print existing records simpledb = Import('simpledb') cds = simpledb.read('mycds.db') if cds: print '<table border="1">' print '<tr><th>Artist</th><th>Title</th>' if logged: print '<th> </th>'*2 print '</tr>' for num,(artist,title) in enumerate(cds): print '<tr><td>%s</td><td>%s</td>' %(artist, title) if logged: print '<td><a href="edit?num=%s">Edit</a></td>' %num print '<td><a href="remove?num=%s">Remove</a></td>' %num print '</tr>' print '</table><p>' else: print "No CD in the collection<p>"
and add a new function, remove():
def remove(num): cds = simpledb.read('mycds.db') del cds[int(num)] simpledb.save(cds,'mycds.db') raise HTTP_REDIRECTION,"index"
Summary
editWe now have a complete application to manage our CD collection. The structure of the application in the script index.ks is as clear as in any Python module :
simpledb = Import('simpledb') def index(): ... # login / logout ... # print existing records ... # prompt logged in users to enter a new record ... # page counter ... def login(): ... def check_login(login,passwd): ... def logout(): ... def new_cd(): ... def insert_new_cd(artist,title): ... def edit(num): ... def update_cd(num,artist,title): ... def remove(num): ...
Each function matches a page of the application. For the pages that receive user input, the fields are the arguments to the function (always as strings)
Throughout this short presentation you see that all you need to know is Python and HTML. The package doesn't require any configuration, and for programmers Karrigell only provides a small set of additional built-in names