Полиморфные ассоциации с SQLAlchemy
пытаюсь реализовать полиморфную ассоциацию с помощью библиотеки SQLAlchemy и использую для этого пример:
но есть одна несовместимость с моим делом. В Примере: объекты Address созданы, а затем добавлены к поставщику или клиенту (таким образом, таблица Address имеет полиморфный внешний ключ к таблицам Supplier и Customer и Backref объекта Supplier и Customer к адресу). Пока объект адреса добавляет к одна из этих таблиц SQLAlchemy автоматически решает, как назначить идентификаторы на таблицах. Затем объект поставщика или клиента можно получить, используя поле "родитель" адреса.
хотя в моем случае мне нужно сначала создать объект адреса, а затем назначить родительскому объекту адрес (например, компания, например, поставщик и клиент).
пример использования полиморфной ассоциации в моем случае:
engine = create_engine('sqlite://', echo=True)
Base.metadata.create_all(engine)
session = Session(engine)
address = Address(street='2569 west elm', city="Detroit", zip="56785")
cust = Customer(name="Tester")
supl = Supplier(company_name="Ace Hammers")
address.parent = supl
session.add_all([address])
session.commit()
но если я попытаюсь применить этот шаблон для моего дела без изменений, я получаю следующее сообщение об ошибке:
Traceback (most recent call last): File "discriminator_on_related.py", line 131, in address.parent = supl File "C:Python27libsite-packagessqlalchemy-0.9.3-py2.7-win32.eggsqlalchemyextassociationproxy.py", line 271, in __set__ setattr(obj, self.target_collection, creator(values)) TypeError: __init__() takes exactly 1 argument (2 given)
Как я должен изменить этот шаблон, чтобы он работал?
P. S. Прошу прощения, если это тривиальный вопрос (с SQLAlchemy association_proxy выглядит как какое-то магическое для меня).
1 ответов
извините всех, кто беспокоился в этом вопросе. Может быть, ответ кому-то пригодится. Ответ был слишком прост. Основная моя ошибка заключалась в том, что я использовал сложный пример шаблона в качестве основы для моего случая. Для решения этой задачи требовалось только разбить ее на подзадачи. Таким образом, эта задача состоит из полиморфного наследования с Объединенными таблицами (которые реализуют довольно легко с помощью SQLAlchemy) и установки внешнего ключа на общую (родительскую) таблицу. Это показывает следующий код фрагмент:
@as_declarative()
class Base(object):
@declared_attr
def __tablename__(cls):
return cls.__name__.lower()
id = Column(Integer, primary_key=True)
class CompanyInterface(Base):
discriminator = Column(String)
__mapper_args__ = {"polymorphic_on": discriminator}
class Address(Base):
street = Column(String)
city = Column(String)
zip = Column(String)
company_id = Column(Integer, ForeignKey(CompanyInterface.id))
company = relationship(CompanyInterface)
def __repr__(self):
return ("%s(street=%r, city=%r, zip=%r, company=%r)" %
(self.__class__.__name__, self.street, self.city, self.zip, self.company))
class Customer(CompanyInterface):
id = Column(Integer, ForeignKey(CompanyInterface.id), primary_key=True)
name = Column(String)
__mapper_args__ = {"polymorphic_identity": "Customer"}
class Supplier(CompanyInterface):
id = Column(Integer, ForeignKey(CompanyInterface.id), primary_key=True)
company_name = Column(String)
__mapper_args__ = {"polymorphic_identity": "Supplier"}
engine = create_engine('sqlite:///test/test_me.db', echo=False)
Base.metadata.create_all(engine)
session = Session(engine)
address1 = Address(street='test-1', city="Detroit", zip="56785")
address2 = Address(street='test-2', city="Phoenix", zip="110322")
address3 = Address(street='test-3', city="Washington", zip="432414")
supl1 = Supplier(company_name="Supplier-1 TEST")
supl2 = Supplier(company_name="Supplier-2 TEST")
cust1 = Customer(name="Customer-1 TEST")
cust2 = Customer(name="Customer-2 TEST")
address1.company = supl1
address2.company = cust1
address3.company = cust1
session.add_all([address1, address2, address3])
session.commit()
address3.company = supl2
session.commit()
print "PRINTING, TOTAL = %s" % session.query(Address).count()
for address in session.query(Address):
print "ADDRESS = %s" % address