尝试调整sqlalchemy的多态关联示例时,创建者函数出错

时间:2011-09-28 11:56:59

标签: sqlalchemy polymorphic-associations

我正在查看http://www.sqlalchemy.org/trac/browser/examples/generic_associations/discriminator_on_association.py并尝试将该示例调整为通用且可重复使用的示例。所以我试图抽象出所有类。但是,创建者对象的 new 函数似乎存在错误。

任何人都可以帮我解决这个问题吗?否则,如果我知道什么是错的,我想这将是一个很好的候选者包含在SQLalchemy食谱中。

ERROR:
Traceback (most recent call last):
File "sqlalchemyex.py", line 136, in <module>
    zip="95732")
File "<string>", line 4, in __init__
File "/home/ahmed/dev/pyrenv/lib/python2.6/site-packages/SQLAlchemy-0.6.6-py2.6.egg/sqlalchemy/orm/state.py", line 111, in initialize_instance
    return manager.events.original_init(*mixed[1:], **kwargs)
File "/home/ahmed/dev/pyrenv/lib/python2.6/site-packages/SQLAlchemy-0.6.6-py2.6.egg/sqlalchemy/ext/declarative.py", line 1378, in _declarative_constructor
    setattr(self, k, kwargs[k])
File "/home/ahmed/dev/pyrenv/lib/python2.6/site-packages/SQLAlchemy-0.6.6-py2.6.egg/sqlalchemy/ext/associationproxy.py", line 195, in __set__
    setattr(obj, self.target_collection, creator(values))
File "sqlalchemyex.py", line 28, in <lambda>
    discriminator=discriminator)
TypeError: object.__new__() takes no parameters




from sqlalchemy.schema import Column, ForeignKey
from sqlalchemy.types import String, Integer
from sqlalchemy.ext.declarative import declared_attr, declarative_base
from sqlalchemy.orm import relationship, backref
from sqlalchemy.ext.associationproxy import association_proxy
from sqlalchemy.engine import create_engine
from sqlalchemy.orm.session import sessionmaker
import os


class AssociationBase(object):

    discriminator = Column(String)
    """Refers to the type of parent."""

    @classmethod
    def creator(cls, discriminator):
        """Provide a 'creator' function to use with 
        the association proxy."""

        return lambda associateds:AssociationBase(
                                associateds=associateds, 
                                discriminator=discriminator)

    @property
    def parent(self):
        """Return the parent object."""
        return getattr(self, "%s_parent" % self.discriminator)
    '''
    @property
    def associateds(self):
        return getattr(self, "backref_%s" % self.discriminator)
    '''
class HasPolymorphicParents(object):

    @declared_attr
    def association_id(self):
        cls = self
        foreignkey_assoc_id = "{0}_association.id".format(cls.__name__)
        return Column(Integer, ForeignKey(foreignkey_assoc_id))

    @declared_attr
    def association(self):
        cls = self
        association_class = "{0}Association".format(cls.__name__)
        return relationship(association_class, 
                    backref="associateds".format(cls.__name__))

    parent = association_proxy("association", "parent")


class HasAssociatedsMixin(object):
    @declared_attr
    def association_id(self):
        cls = self
        associated_classname = cls.__associated__
        foreignkey_assoc_id = "{0}_association.id".format(associated_classname)
        return Column(Integer, ForeignKey(foreignkey_assoc_id))

    @declared_attr
    def association(self):
        cls = self
        discriminator = cls.__name__.lower()

        associated_classname = cls.__associated__

        ##########
        assoc_rel = 'associateds'

        assoc_proxy =  association_proxy('association', assoc_rel,
                    creator=self.__assoc_cls__.creator(discriminator)
                    )

        setattr(cls, assoc_rel, assoc_proxy)
        ##########

        association_classname = "{0}Association".format(associated_classname)
        return relationship(association_classname, 
                    backref=backref("%s_parent" % discriminator, uselist=False))

DecBase = declarative_base()

class AddressAssociation(DecBase, AssociationBase, ):
    __tablename__ = "Address_association"
    id = Column(Integer, primary_key=True)

class Address(HasPolymorphicParents, DecBase):
    __tablename__ = 'Addresses'
    id = Column(Integer, primary_key=True)
    street = Column(String)
    city = Column(String)
    zip = Column(String)

class Customer(HasAssociatedsMixin, DecBase):
    __tablename__ = 'Customers'
    __associated__ = 'Address'
    __assoc_rel__ = 'addresses'
    __assoc_cls__ = AddressAssociation

    id = Column(Integer, primary_key=True)
    name = Column(String)

class Supplier(HasAssociatedsMixin, DecBase):
    __tablename__ = 'Suppliers'
    __associated__ = 'Address'
    __assoc_rel__ = 'addresses'
    __assoc_cls__ = AddressAssociation

    id = Column(Integer, primary_key=True)
    name = Column(String)
    company_name = Column(String)


os.environ['PYTHONINSPECT'] = 'True'    
eng = create_engine('sqlite://')
DecBase.metadata.create_all(eng)
session = sessionmaker(bind=eng)()


session.add_all([
    Customer(
        name='customer 1', 
        associateds=[
            Address(
                    street='123 anywhere street',
                    city="New York",
                    zip="10110"),
            Address(
                    street='40 main street',
                    city="San Francisco",
                    zip="95732")
        ]
    ),
    Supplier(
        company_name="Ace Hammers",
        associateds=[
            Address(
                    street='2569 west elm',
                    city="Detroit",
                    zip="56785")
        ]
    ),
])

session.commit()

for customer in session.query(Customer):
    for address in customer.addresses:
        print address
        print address.parent

1 个答案:

答案 0 :(得分:1)

这是你得到的错误吗?

Traceback (most recent call last):
  File "/tmp/test4.py", line 134, in <module>
    associateds=[
  File "<string>", line 4, in __init__
  File "/usr/lib/python2.7/site-packages/sqlalchemy/orm/state.py", line 98, in initialize_instance
    return manager.original_init(*mixed[1:], **kwargs)
  File "/usr/lib/python2.7/site-packages/sqlalchemy/ext/declarative.py", line 1388, in _declarative_constructor
    setattr(self, k, kwargs[k])
  File "/usr/lib/python2.7/site-packages/sqlalchemy/ext/associationproxy.py", line 201, in __set__
    setattr(obj, self.target_collection, creator(values))
  File "/tmp/test4.py", line 23, in <lambda>
    discriminator=discriminator)
TypeError: object.__new__() takes no parameters