summaryrefslogtreecommitdiff
path: root/examples/poly_assoc
diff options
context:
space:
mode:
authorMike Bayer <mike_mp@zzzcomputing.com>2011-04-27 22:33:37 -0400
committerMike Bayer <mike_mp@zzzcomputing.com>2011-04-27 22:33:37 -0400
commitd03226426c24eef5c9e19822ff07a5f72dd5379f (patch)
tree4d4520085485e397f11c23248733bab1e30dfd7e /examples/poly_assoc
parent7df21e5a1f252ff768f684132db95bd1b5e78efa (diff)
downloadsqlalchemy-d03226426c24eef5c9e19822ff07a5f72dd5379f.tar.gz
- removed the ancient "polymorphic association"
examples and replaced with an updated set of examples that use declarative mixins, "generic_associations". Each presents an alternative table layout.
Diffstat (limited to 'examples/poly_assoc')
-rw-r--r--examples/poly_assoc/__init__.py10
-rw-r--r--examples/poly_assoc/poly_assoc.py156
-rw-r--r--examples/poly_assoc/poly_assoc_fk.py164
-rw-r--r--examples/poly_assoc/poly_assoc_generic.py161
4 files changed, 0 insertions, 491 deletions
diff --git a/examples/poly_assoc/__init__.py b/examples/poly_assoc/__init__.py
deleted file mode 100644
index 19836a742..000000000
--- a/examples/poly_assoc/__init__.py
+++ /dev/null
@@ -1,10 +0,0 @@
-"""
-Illustrates polymorphic associations, a method of associating a particular child object with many different types of parent object.
-
-This example is based off the original blog post at `<http://techspot.zzzeek.org/?p=13>`_ and illustrates three techniques:
-
-* ``poly_assoc.py`` - imitates the non-foreign-key schema used by Ruby on Rails' Active Record.
-* ``poly_assoc_fk.py`` - Adds a polymorphic association table so that referential integrity can be maintained.
-* ``poly_assoc_generic.py`` - further automates the approach of ``poly_assoc_fk.py`` to also generate the association table definitions automatically.
-
-""" \ No newline at end of file
diff --git a/examples/poly_assoc/poly_assoc.py b/examples/poly_assoc/poly_assoc.py
deleted file mode 100644
index 1854bfa3d..000000000
--- a/examples/poly_assoc/poly_assoc.py
+++ /dev/null
@@ -1,156 +0,0 @@
-"""
-"polymorphic" associations, ala ActiveRecord.
-
-In this example, we are specifically targeting this ActiveRecord
-functionality:
-
-http://wiki.rubyonrails.org/rails/pages/UnderstandingPolymorphicAssociations
-
-The term "polymorphic" here means "object X can be referenced by objects A, B,
-and C, along a common line of association".
-
-In this example we illustrate the relationship in both directions. A little
-bit of property magic is used to smooth the edges.
-
-AR creates this relationship in such a way that disallows any foreign key
-constraint from existing on the association. For a different way of doing
-this, see poly_assoc_fks.py. The interface is the same, the efficiency is more
-or less the same, but foreign key constraints may be used. That example also
-better separates the associated target object from those which associate with
-it.
-
-"""
-
-from sqlalchemy import MetaData, Table, Column, Integer, String, and_
-from sqlalchemy.orm import mapper, relationship, sessionmaker, \
- class_mapper, backref
-
-metadata = MetaData('sqlite://')
-
-#######
-# addresses table, class, 'addressable interface'.
-
-addresses = Table("addresses", metadata,
- Column('id', Integer, primary_key=True),
- Column('addressable_id', Integer),
- Column('addressable_type', String(50)),
- Column('street', String(100)),
- Column('city', String(50)),
- Column('country', String(50))
- )
-
-class Address(object):
- def __init__(self, type):
- self.addressable_type = type
- @property
- def member(self):
- return getattr(self, '_backref_%s' % self.addressable_type)
-
-def addressable(cls, name, uselist=True):
- """addressable 'interface'.
-
- if you really wanted to make a "generic" version of this function, it's
- straightforward.
- """
-
- # create_address function, imitaes the rails example.
- # we could probably use property tricks as well to set
- # the Address object's "addressabletype" attribute.
- def create_address(self):
- a = Address(table.name)
- if uselist:
- getattr(self, name).append(a)
- else:
- setattr(self, name, a)
- return a
-
- mapper = class_mapper(cls)
- table = mapper.local_table
- cls.create_address = create_address
- # no constraints. therefore define constraints in an ad-hoc fashion.
- primaryjoin = and_(
- list(table.primary_key)[0] == addresses.c.addressable_id,
- addresses.c.addressable_type == table.name
- )
- foreign_keys = [addresses.c.addressable_id]
- mapper.add_property(name, relationship(
- Address,
- primaryjoin=primaryjoin,
- uselist=uselist,
- foreign_keys=foreign_keys,
- backref=backref('_backref_%s' % table.name,
- primaryjoin=list(table.primary_key)[0] ==\
- addresses.c.addressable_id,
- foreign_keys=foreign_keys)
- )
- )
-
-mapper(Address, addresses)
-
-######
-# sample # 1, users
-
-users = Table("users", metadata,
- Column('id', Integer, primary_key=True),
- Column('name', String(50), nullable=False)
- )
-
-class User(object):
- pass
-
-mapper(User, users)
-addressable(User, 'addresses', uselist=True)
-
-######
-# sample # 2, orders
-
-orders = Table("orders", metadata,
- Column('id', Integer, primary_key=True),
- Column('description', String(50), nullable=False))
-
-class Order(object):
- pass
-
-mapper(Order, orders)
-addressable(Order, 'address', uselist=False)
-
-
-######
-# use it !
-metadata.create_all()
-
-u1 = User()
-u1.name = 'bob'
-
-o1 = Order()
-o1.description = 'order 1'
-
-a1 = u1.create_address()
-a1.street = '123 anywhere street'
-a2 = u1.create_address()
-a2.street = '345 orchard ave'
-
-a3 = o1.create_address()
-a3.street = '444 park ave.'
-
-sess = sessionmaker()()
-sess.add(u1)
-sess.add(o1)
-
-sess.commit()
-
-# query objects, get their addresses
-
-bob = sess.query(User).filter_by(name='bob').one()
-assert [s.street for s in bob.addresses] == ['123 anywhere street', '345 orchard ave']
-
-order = sess.query(Order).filter_by(description='order 1').one()
-assert order.address.street == '444 park ave.'
-
-# query from Address to members
-
-for address in sess.query(Address).all():
- print "Street", address.street, "Member", address.member
-
-
-
diff --git a/examples/poly_assoc/poly_assoc_fk.py b/examples/poly_assoc/poly_assoc_fk.py
deleted file mode 100644
index a22020e08..000000000
--- a/examples/poly_assoc/poly_assoc_fk.py
+++ /dev/null
@@ -1,164 +0,0 @@
-"""
-"polymorphic" associations, ala SQLAlchemy.
-
-See "poly_assoc.py" for an imitation of this functionality as implemented in
-ActiveRecord.
-
-Here, we build off the previous example, adding an association table that
-allows the relationship to be expressed as a many-to-one from the "model"
-object to its "association", so that each model table bears the foreign key
-constraint. This allows the same functionality via traditional normalized form
-with full constraints. It also isolates the target associated object from its
-method of being associated, allowing greater flexibility in its usage.
-
-As in the previous example, a little bit of property magic is used to smooth
-the edges.
-
-For a more genericized version of this example, see poly_assoc_generic.py.
-"""
-
-from sqlalchemy import MetaData, Table, Column, Integer, String, \
- ForeignKey
-from sqlalchemy.orm import mapper, relationship, sessionmaker, \
- class_mapper
-
-metadata = MetaData('sqlite://')
-
-#######
-# addresses table, class, 'addressable interface'.
-
-addresses = Table("addresses", metadata,
- Column('id', Integer, primary_key=True),
- Column('assoc_id', None, ForeignKey('address_associations.assoc_id')),
- Column('street', String(100)),
- Column('city', String(50)),
- Column('country', String(50))
- )
-
-## association table
-address_associations = Table("address_associations", metadata,
- Column('assoc_id', Integer, primary_key=True),
- Column('type', String(50), nullable=False)
-)
-
-class Address(object):
-
- @property
- def member(self):
- return getattr(self.association, '_backref_%s'
- % self.association.type)
-
-class AddressAssoc(object):
- def __init__(self, name):
- self.type = name
-
-def addressable(cls, name, uselist=True):
- """addressable 'interface'.
-
- we create this function here to imitate the style used in poly_assoc.py.
-
- """
- mapper = class_mapper(cls)
- table = mapper.local_table
- mapper.add_property('address_rel',
- relationship(AddressAssoc,
- backref='_backref_%s' % table.name)
- )
-
- if uselist:
- # list based property decorator
- def get(self):
- if self.address_rel is None:
- self.address_rel = AddressAssoc(table.name)
- return self.address_rel.addresses
- setattr(cls, name, property(get))
- else:
- # scalar based property decorator
- def get(self):
- return self.address_rel.addresses[0]
- def set(self, value):
- if self.address_rel is None:
- self.address_rel = AddressAssoc(table.name)
- self.address_rel.addresses = [value]
- setattr(cls, name, property(get, set))
-
-mapper(Address, addresses)
-
-mapper(AddressAssoc, address_associations, properties={
- 'addresses':relationship(Address, backref='association'),
-})
-
-######
-# sample # 1, users
-
-users = Table("users", metadata,
- Column('id', Integer, primary_key=True),
- Column('name', String(50), nullable=False),
- # this column ties the users table into the address association
- Column('assoc_id', Integer, ForeignKey('address_associations.assoc_id'))
- )
-
-class User(object):
- pass
-
-mapper(User, users)
-addressable(User, 'addresses', uselist=True)
-
-######
-# sample # 2, orders
-
-orders = Table("orders", metadata,
- Column('id', Integer, primary_key=True),
- Column('description', String(50), nullable=False),
- # this column ties the orders table into the address association
- Column('assoc_id', Integer, ForeignKey('address_associations.assoc_id'))
- )
-
-class Order(object):
- pass
-
-mapper(Order, orders)
-addressable(Order, 'address', uselist=False)
-
-######
-# use it !
-metadata.create_all()
-
-u1 = User()
-u1.name = 'bob'
-
-o1 = Order()
-o1.description = 'order 1'
-
-# note we can just create an Address object freely.
-# if you want a create_address() function, just stick it on the class.
-a1 = Address()
-u1.addresses.append(a1)
-a1.street = '123 anywhere street'
-
-a2 = Address()
-u1.addresses.append(a2)
-a2.street = '345 orchard ave'
-
-o1.address = Address()
-o1.address.street = '444 park ave.'
-
-sess = sessionmaker()()
-sess.add(u1)
-sess.add(o1)
-
-sess.commit()
-
-# query objects, get their addresses
-
-bob = sess.query(User).filter_by(name='bob').one()
-assert [s.street for s in bob.addresses] == \
- ['123 anywhere street', '345 orchard ave']
-
-order = sess.query(Order).filter_by(description='order 1').one()
-assert order.address.street == '444 park ave.'
-
-# query from Address to members
-
-for address in sess.query(Address).all():
- print "Street", address.street, "Member", address.member
diff --git a/examples/poly_assoc/poly_assoc_generic.py b/examples/poly_assoc/poly_assoc_generic.py
deleted file mode 100644
index b674e1eb8..000000000
--- a/examples/poly_assoc/poly_assoc_generic.py
+++ /dev/null
@@ -1,161 +0,0 @@
-"""
-"polymorphic" associations, ala SQLAlchemy.
-
-This example generalizes the function in poly_assoc_pk.py into a function
-"association" which creates a new polymorphic association "interface".
-"""
-
-from sqlalchemy import MetaData, Table, Column, Integer, String, \
- ForeignKey
-from sqlalchemy.orm import mapper, relationship, sessionmaker, \
- class_mapper
-
-metadata = MetaData('sqlite://')
-
-def association(cls, table):
- """create an association 'interface'."""
-
- interface_name = table.name
- attr_name = "%s_rel" % interface_name
-
- metadata = table.metadata
- association_table = Table("%s_associations" % interface_name, metadata,
- Column('assoc_id', Integer, primary_key=True),
- Column('type', String(50), nullable=False)
- )
-
- class GenericAssoc(object):
- def __init__(self, name):
- self.type = name
-
- def interface(cls, name, uselist=True):
-
- mapper = class_mapper(cls)
- table = mapper.local_table
- mapper.add_property(attr_name,
- relationship(GenericAssoc,
- backref='_backref_%s' % table.name)
- )
-
- if uselist:
- # list based property decorator
- def get(self):
- if getattr(self, attr_name) is None:
- setattr(self, attr_name, GenericAssoc(table.name))
- return getattr(self, attr_name).targets
- setattr(cls, name, property(get))
- else:
- # scalar based property decorator
- def get(self):
- return getattr(self, attr_name).targets[0]
- def set(self, value):
- if getattr(self, attr_name) is None:
- setattr(self, attr_name, GenericAssoc(table.name))
- getattr(self, attr_name).targets = [value]
- setattr(cls, name, property(get, set))
-
- @property
- def member(self):
- return getattr(self.association,
- '_backref_%s' % self.association.type)
-
- setattr(cls, 'member', member)
-
- mapper(GenericAssoc, association_table, properties={
- 'targets':relationship(cls, backref='association'),
- })
-
- return interface
-
-
-#######
-# addresses table
-
-addresses = Table("addresses", metadata,
- Column('id', Integer, primary_key=True),
- Column('assoc_id', Integer, ForeignKey('addresses_associations.assoc_id')),
- Column('street', String(100)),
- Column('city', String(50)),
- Column('country', String(50))
- )
-
-class Address(object):
- pass
-
-# create "addressable" association
-addressable = association(Address, addresses)
-
-mapper(Address, addresses)
-
-
-######
-# sample # 1, users
-
-users = Table("users", metadata,
- Column('id', Integer, primary_key=True),
- Column('name', String(50), nullable=False),
- Column('assoc_id', Integer, ForeignKey('addresses_associations.assoc_id'))
- )
-
-class User(object):
- pass
-
-mapper(User, users)
-
-# use the association
-addressable(User, 'addresses', uselist=True)
-
-######
-# sample # 2, orders
-
-orders = Table("orders", metadata,
- Column('id', Integer, primary_key=True),
- Column('description', String(50), nullable=False),
- Column('assoc_id', Integer, ForeignKey('addresses_associations.assoc_id'))
- )
-
-class Order(object):
- pass
-
-mapper(Order, orders)
-addressable(Order, 'address', uselist=False)
-
-######
-# use it !
-metadata.create_all()
-
-u1 = User()
-u1.name = 'bob'
-
-o1 = Order()
-o1.description = 'order 1'
-
-a1 = Address()
-u1.addresses.append(a1)
-a1.street = '123 anywhere street'
-
-a2 = Address()
-u1.addresses.append(a2)
-a2.street = '345 orchard ave'
-
-o1.address = Address()
-o1.address.street = '444 park ave.'
-
-sess = sessionmaker()()
-sess.add(u1)
-sess.add(o1)
-sess.commit()
-
-# query objects, get their addresses
-
-bob = sess.query(User).filter_by(name='bob').one()
-assert [s.street for s in bob.addresses] == \
- ['123 anywhere street', '345 orchard ave']
-
-order = sess.query(Order).filter_by(description='order 1').one()
-assert order.address.street == '444 park ave.'
-
-# query from Address to members
-
-for address in sess.query(Address).all():
- print "Street", address.street, "Member", address.member