[SQL-CVS] r1018 - SQLObject/trunk/docs
SQLObject is a Python ORM.
Brought to you by:
ianbicking,
phd
|
From: <sub...@co...> - 2005-09-21 14:18:17
|
Author: phd
Date: 2005-09-21 14:18:05 +0000 (Wed, 21 Sep 2005)
New Revision: 1018
Modified:
SQLObject/trunk/docs/Inheritance.txt
Log:
Added a section "Why" describing a typical use of Inheritance.
Modified: SQLObject/trunk/docs/Inheritance.txt
===================================================================
--- SQLObject/trunk/docs/Inheritance.txt 2005-09-21 07:54:21 UTC (rev 1017)
+++ SQLObject/trunk/docs/Inheritance.txt 2005-09-21 14:18:05 UTC (rev 1018)
@@ -3,6 +3,170 @@
Inheritance
-----------
+Why
+~~~
+
+Imagine you have a list or persons, and every person plays a certain role.
+Some persons are students, some are professors, some are employees. Every
+role has different attributes. Students are known by their department and
+year. Professors has department (some attributes are common for all or some
+roles), timetable and other attributes.
+
+How do one implements this in SQL? Well, the obvious approach is to create
+a table Person with a column that describes or name the role, and a table
+for an every role. Then one must write a code that interprets and
+dereferences the role column.
+
+Well, the inheritance machinery described below does exactly this! Only it
+does it automagically and mostly transparent to the user.
+
+First, you create a table Person. Nothing magical here::
+
+ class Person(SQLObject):
+ name = StringCol()
+ age = FloatCol()
+
+Now you need a hierarchy of roles::
+
+ class Role(InheritableSQLObject):
+ department = StringCol()
+
+The magic starts here! You inherit the class from the special root class
+``InheritableSQLObject`` and provide a set of attributes common for all
+roles. Other roles must be inherited from Role::
+
+ class Student(Role):
+ year = IntCol()
+
+ class Professor(Role):
+ timetable = StringCol()
+
+Now you want a column in Person that can be interpreted as the role. Easy::
+
+ class Person(SQLObject):
+ name = StringCol()
+ age = FloatCol()
+ role = ForeignKey("Role")
+
+That's all, really! When asked for its role, Person returns the value of
+its .role attribute dereferenced and interpreted. Instead of returning an
+instance of class Role it returns an instance of the corresponding subclass
+- a Student or a Professor.
+
+This is a brief explanation based on a task people meet most often, but of
+course it can be used far beyond the person/role task. I also omitted all
+details in the explanation. Now look at the real working program::
+
+ from sqlobject import *
+ from sqlobject.inheritance import InheritableSQLObject
+
+ __connection__ = "sqlite:/:memory:"
+
+ class Role(InheritableSQLObject):
+ department = StringCol()
+
+ class Student(Role):
+ year = IntCol()
+
+ class Professor(Role):
+ timetable = StringCol(default=None)
+
+ class Person(SQLObject):
+ name = StringCol()
+ age = FloatCol()
+ role = ForeignKey("Role", default=None)
+
+ Role.createTable()
+ Student.createTable()
+ Professor.createTable()
+ Person.createTable()
+
+ first_year = Student(department="CS", year=1)
+ lecturer = Professor(department="Mathematics")
+
+ student = Person(name="A student", age=21, role=first_year)
+ professor = Person(name="A professor", age=42, role=lecturer)
+
+ print student.role
+ print professor.role
+
+It prints::
+
+ <Student 1 year=1 department='CS'>
+ <Professor 2 timetable=None department='Mathematics'>
+
+You can get the list of all available roles::
+
+ print list(Role.select())
+
+It prints::
+
+ [<Student 1 year=1 department='CS'>, <Professor 2 timetable=None department='Mathematics'>]
+
+Look, you have got a list of Role's subclasses!
+
+If you add a MultipleJoin column to Role you can list all persons for a
+given role::
+
+ class Role(InheritableSQLObject):
+ department = StringCol()
+ persons = MultipleJoin("Person")
+
+ for role in Role.select():
+ print role.persons
+
+It prints::
+
+ [<Person 1 name='A student' age=21.0 roleID=1>]
+ [<Person 2 name='A professor' age=42.0 roleID=2>]
+
+If you you want your persons to have many roles - use RelatedJoin::
+
+ class Role(InheritableSQLObject):
+ department = StringCol()
+ persons = RelatedJoin("Person")
+
+ class Student(Role):
+ year = IntCol()
+
+ class Professor(Role):
+ timetable = StringCol(default=None)
+
+ class Person(SQLObject):
+ name = StringCol()
+ age = FloatCol()
+ roles = RelatedJoin("Role")
+
+ Role.createTable()
+ Student.createTable()
+ Professor.createTable()
+ Person.createTable()
+
+ first_year = Student(department="CS", year=1)
+ lecturer = Professor(department="Mathematics")
+
+ student = Person(name="A student", age=21)
+ student.addRole(first_year)
+ professor = Person(name="A professor", age=42)
+ professor.addRole(lecturer)
+
+ print student.roles
+ print professor.roles
+
+ for role in Role.select():
+ print role.persons
+
+It prints::
+
+ [<Student 1 year=1 department='CS'>]
+ [<Professor 2 timetable=None department='Mathematics'>]
+ [<Person 1 name='A student' age=21.0>]
+ [<Person 2 name='A professor' age=42.0>]
+
+
+Who, What and How
+~~~~~~~~~~~~~~~~~
+
Daniel Savard has implemented inheritance for SQLObject. According to
ObjectMatter_ this is a kind of vertical inheritance. The only difference
is that objects reference their leafs, not parents. Links to parents are
@@ -18,7 +182,6 @@
* This version now seems to works correctly with addColumn, delColumn,
addJoin and delJoin.
-
The following code::
from sqlobject.inheritance import InheritableSQLObject
@@ -44,7 +207,6 @@
position TEXT
)
-
A new class attribute ``_inheritable`` is added. When this new
attribute is set to 1, the class is marked 'inheritable' and a new
columns will automatically be added: childName (TEXT).
@@ -87,7 +249,6 @@
1
Chief
-
You will still be able to ask for the attribute normally:
e.firstName will return Jane and setting it will write the new value in
the person table.
@@ -117,8 +278,10 @@
FROM person, employee WHERE person.first_name = 'Jane'
AND employee.position = 'Chief' AND person.id = employee.id
-Some limitation or notice about this version:
+Limitations and notes
+~~~~~~~~~~~~~~~~~~~~~
+
* Only simple inheritance will work. It is not possible to inherit
from multiple SQLObject classes.
* It is possible to inherit from an inherited class and this will
|