A simple model

The first example shows a model for a simple movie database. Movies can have actors, directors, multiple genres, they have a title and a year.

This example also shows how easily real polymorphic inheritance can be used: actors and directors are artists. That is, each property or relationship you add to the Artist-class will be availlable for Actors as well as for Directors, in this case it's the artist's name and date of birth.

#!/usr/bin/env python

import sqlalchemy

from turboentity import *
from turboentity import objectstore

metadata = sqlalchemy.BoundMetaData("sqlite:///:memory:")

class Genre (Entity):
    title = Column(Unicode(30))
    movies = ManyToMany("Movie")

class Movie (Entity):   
    title = Column(Unicode(50))
    year = Column(Integer)
    genres = ManyToMany("Genre")
    director = ManyToOne("Director")
    actors = ManyToMany("Actor")
    def genre(self):
        return " / ".join(genre.title for genre in self.genres)

class Artist (Entity):
    firstname = Column(Unicode(30))
    lastname = Column(Unicode(30))
    birthdate = Column(Date)
    def name(self):
        return self.firstname +" "+ self.lastname

class Director (Artist):
    movies = OneToMany("Movie")

class Actor (Artist):
    movies = ManyToMany("Movie")

def main():
    create_all() # create all tables
    scifi = Genre(title="Science-Fiction")
    fantasy = Genre(title="Fantasy")
    horror = Genre(title="Horror")
    rscott = Director(lastname="Scott", firstname="Ridley")
    glucas = Director(lastname="Lucas", firstname="George")
    sweaver = Actor(lastname="Weaver", firstname="Sigourney")
    hford = Actor(lastname="Ford", firstname="Harrison")
    syoung = Actor(lastname="Young", firstname="Sean")
    mhamill = Actor(lastname="Hamill", firstname="Mark")
    cfisher = Actor(lastname="Fisher", firstname="Carrie")
    blade_runner = Movie(title="Blade Runner", year=1982)
    blade_runner.director = rscott
    alien = Movie(title="Alien", year=1979)
    alien.director = rscott
    star_wars = Movie(title="Star Wars", year=1977)
    star_wars.director = glucas
    for movie in Movie.select():
        print "Movie:       %s" % movie.title
        print "Year:        %d" % movie.year
        print "Genre:       %s" % movie.genre
        print "Directed by: %s" % movie.director.name
        print "Cast:        %s,.." % ", ".join(actor.name
                                            for actor in movie.actors)

if __name__ == '__main__':

View plaintext/download: simple.py


Self-referential relationships

In this example there is a simple father-children relationship, so you can see how self-referential relationships work. Furthermore this shows how you can tweak some entity-specific settings by providing an inner class named "turboentity":

#!/usr/bin/env python

import sqlalchemy
from turboentity import *
from turboentity import objectstore

metadata = sqlalchemy.BoundMetaData("sqlite:///:memory:")

class Person (Entity):
    class turboentity:
        tablename = "some_human_lifeform"
        order_by = "name"

    name = Column(Unicode(30))
    father = ManyToOne("Person")
    children = OneToMany("Person")

def main():

    grampa = Person(name="Abe")
    homer = Person(name="Homer")
    bart = Person(name="Bart")
    lisa = Person(name="Lisa")

    lisa.father = homer


    p = Person.get_by(name="Homer")
    print "%s is %s's child." % (p.name, p.father.name)
    print "His children are %s." % (
            " and ".join(c.name for c in p.children))

if __name__ == '__main__':

View plaintext/download: selfref.py


TurboGears identity model

And finally, here's the model.py you can use as a starting point for your identity-based TurboGears-projects. Simply start your new TurboGears-project by typing

tg-admin quickstart -i -s {ProjectName}

and replace the generated model.py with the attached file below. Automatic table creation works as normal:

tg-admin sql create

at least with TurboGears 1.1a0 (r2032).

This Example also shows how TurboEntity can improve the readability of your sourcecode.

from datetime import datetime
from turbogears.database import metadata, session
from turbogears import identity 
from turboentity import *

class Visit (Entity):
    class turboentity:
        tablename = "visit"
    visit_key = Column(String(40), primary_key=True)
    created = Column(DateTime, nullable=False, default=datetime.now)
    expiry = Column(DateTime)

    def lookup_visit(cls, visit_key):
        return Visit.get(visit_key)

class VisitIdentity (Entity):
    class turboentity:
        tablename = "visit_identity"

    visit_key = Column(String(40), primary_key=True)
    user_id = Column(Integer, ForeignKey("tg_user.user_id"), index=True)

class Group (Entity):
        An ultra-simple group definition.
    class turboentity:
        tablename = "tg_group"
    group_id = Column(Integer, primary_key=True)
    group_name = Column(Unicode(16), unique=True)
    display_name = Column(Unicode(255))
    created = Column(DateTime, default=datetime.now)
    users = ManyToMany("User")
    permissions = ManyToMany("Permission")

class User (Entity):
        Reasonably basic User definition. Probably
        would want additional attributes.
    class turboentity:
        tablename = "tg_user"

    user_id = Column(Integer, primary_key=True)
    user_name = Column(Unicode(16), unique=True)
    email_address = Column(Unicode(255), unique=True)
    display_name = Column(Unicode(255))
    password = Column(Unicode(40))
    created = Column(DateTime, default=datetime.now)
    groups = ManyToMany("Group")

    def permissions(self):
        perms = set()
        for g in self.groups:
            perms = perms | set(g.permissions)
        return perms

class Permission (Entity):   
    class turboentity:
        tablename = "tg_permission"
    permission_id = Column(Integer, primary_key=True)
    permission_name = Column(Unicode(16), unique=True)
    description = Column(Unicode(255))

    groups = ManyToMany("Group")

View plaintext/download: model.py