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")
@property
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)
@property
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.actors.append(hford)
blade_runner.actors.append(syoung)
blade_runner.director = rscott
alien = Movie(title="Alien", year=1979)
alien.actors.append(sweaver)
alien.director = rscott
star_wars = Movie(title="Star Wars", year=1977)
star_wars.actors.append(cfisher)
star_wars.actors.append(hford)
star_wars.actors.append(mhamill)
star_wars.director = glucas
star_wars.genres.append(scifi)
star_wars.genres.append(fantasy)
scifi.movies.append(blade_runner)
scifi.movies.append(alien)
alien.genres.append(horror)
objectstore.flush()
objectstore.clear()
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)
print
if __name__ == '__main__':
main()
View plaintext/download: simple.py
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():
create_all()
grampa = Person(name="Abe")
homer = Person(name="Homer")
bart = Person(name="Bart")
lisa = Person(name="Lisa")
grampa.children.append(homer)
homer.children.append(bart)
lisa.father = homer
objectstore.flush()
objectstore.clear()
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__':
main()
View plaintext/download: selfref.py
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)
@classmethod
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")
@property
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