Relational Databases


Consider an address-book like application that allows you to manage a list of people (contacts) and put them into groups.

The database for such an application consists of:
  •     a Person table for the people. Each person record would be assigned a key.
  •     a Group table to define groups. Each group would be assigned a key.
  •     a Person-Group table to define which people are in which groups. This table relates people and groups.
James's Address Book
 Person
name       key
 Joe 1
 Bill    2
 Mary 3
 Group
name          key
 friends1
 colleagues 2

PersonGroup
pkey    gkey
 1 1
 2   1
 3 2

For the above table, who is in James's friends group? Who are James's colleagues?

In this case, the relationships are many-to-many, as a person could be in both the friends and colleagues group, and each group can have more than one member. You can also have one-to-many relationships.

Relational Database with Google's Appengine

Consider a simple person book application that allows you to add people into groups. With AppEngine, you could set up the following classes:

 class Person(db.Model):
          first=db.StringProperty()
          last=db.StringProperty()
 class Group:
        name=db.StringProperty()
 class PersonGroup:
    group = db.ReferenceProperty(Group)
    person = db.ReferenceProperty(Person)


Note that you'd have some additional data members and functions as well (the code for a full sample is attached).

ReferenceProperties
The mapping class (table) PersonGroup has two reference properties. Beneath the hood, the table has a group key and person key stored for each row.

Given such classes, you can get the members of a group and the groups of a person. For our example, class Person has a

When you define a ReferenceProperty, AppEngine makes available a property in the class being referenced. For the example, Group and Person will have a property 'persongroup_set'. This is a list of all the PersonGroups for the particular person or group.

Using this, you can get the members of a group with:
class Group:
  name = db.StringProperty()
  
  def members(self):
    mems=[]
    personGroups = self.persongroup_set   # same as saying
    for pg in personGroups:
        mems.append(pg.person)
    return mems

Here, we use the automatic property persongroup_set to get a list of the PersonGroup records for this group. We then loop through and grab the group from each of those.

Note that persongroup_set is really short hand for querying the PersonGroup table. Instead of 'self.persongroup_set' in the code above, you could call:

db.GQLQuery("Select * from PersonGroup Where group=:1",self)

Instructor sample

1. Show the different ways that we can get members.
   -- using persongroup_set
   -- not using persongroup_set but querying PersonGroup explicitly
   -- using Python generator

2. Code the method 'groups' in the Person class

In-Class Worksheet
1. The PersonGroup sample lets all users modify the same list of people and groups. What if you wanted to let each user keep track of their own people and groups? With pencil and paper, sketch out the changes you'd need.

2. Download the attached code into a directory personGroupBook. You'll also need to cut and paste the HTML files groups.html and index.html listed at the bottom of this document. Get the code to run with dev_appserver.

3. Modify your personGroupBook by creating a profile page. This page should list the person's name and all of its groups, and it should allow the user to add a person to any group.

a. Create person.html which shows the person's name, a dynamic list of groups, and checkboxes and a button for adding new groups. The easiest way is to copy group.html into person.html as they are very similar.

b. Add two controller methods, one for when the person page is loaded and one for when the user adds a group to a person from the person.html page. You'll need to add corresponding entries for the controller methods to the mapping at the bottom of the controller.

c. Modify index.html and MainController so that each person listed on the main page is linkable.

****HTML FILES for sample****

group.html:

<html>
  <body>
   Group: {{ group.name }}<br/>
   {% for member in group.members %}
      
        <b>{{member.first}} &nbsp; {{member.last}}</b><br/>
   {% endfor %}<br/>
  
   <h3>Add members</h3>
   <form action="/on_to_group" method="post">
      {% for person in people %}    
   
        <b>{{person.first}} &nbsp; {{person.last}}</b><input type="checkbox" name="person_check" value={{person.key}}>
    <input type="hidden" name="group_name" value={{group.name}}>
      {% endfor %}
      <input type="submit" value="add to group">
    </form>
  </body>
</html>

and index.html:

<html>
  <body>
    <h3>hello {{user.nickname}}</h3>
    <h2>People</h2>
    {% for person in people %}
        <b>{{person.first}} &nbsp; {{person.last}}</b><br/>
    {% endfor %}

    <h2>Add a new person to the database</h2>
    <form action="/on_add_person" method="post">
      <div>first:<input type="text" name="first"></div>
      <div>last:<input type="text" name="last"></div>   
      <div><input type="submit" value="Add Person"></div>
    </form>

     <h2>Groups</h2>
    {% for group in groups %}    
        <b><a href=group?name={{group.name}} >{{group.name}}</a> </b><br/>
    {% endfor %}

    <h2>Add a new group to the database</h2>
    <form action="/on_add_group" method="post">
      <div>name:<input type="text" name="name"></div>    
      <div><input type="submit" value="Add Group"></div>
    </form>

 </body>
</html>

**********************************************************
More information: Check out this Google article


Attachments (4)

Recent site activity