Karrigell/Managing The Database

      Database engine

      Karrigell 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

      ↑Jump back a section

      Home page with the CD list

      We 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

      ↑Jump back a section

      Adding new CDs

      For 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

      ↑Jump back a section

      Editing records

      Logged-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"
      
      ↑Jump back a section

      Removing records

      The 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"
      
      ↑Jump back a section

      Summary

      We 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

      ↑Jump back a section
      Last modified on 21 September 2010, at 13:46