SQLAlchemy:如何创建1:n关系?

时间:2017-08-22 17:07:04

标签: python python-2.7 sqlalchemy

我即将使用SQLAlchey创建一个特定的1:n-realtionship。

我为你带了两张照片,所以你可以看到这是什么。首先,您将看到EER模型的图片。在此EER模型中,我在 person 表和 family 表之间创建了1:n关系。任何人都存储在 person 表中。我们都知道人们可以彼此建立关系(母亲,父亲,女儿,儿子,堂兄,堂兄,侄子等......)。出于这个原因,我已经设置了 family 表。

enter image description here

为了让整个时间充当示范,我用虚拟数据填充了表格。看一下家庭表,我们在第一栏中看到,这是中心人物,即Hans Schmidt(ID为1)。在家庭表中,以下人员通过外键保存:Kurt Schmidt(儿子),Gerda Schmidt(妻子),Gisela Schmidt(Hans的母亲)和Julia Schmidt(女儿)。我想指出Hans Schmidt的关系。

enter image description here

在我的源代码中,我已按如下方式映射此ORM模型:

class FAMILY(Base):

    __tablename__ = "family"

    id = Column(Integer, primary_key=True, unique=True, autoincrement=True)
    status = Column(String(255), nullable=False)

    person_id = Column(Integer, ForeignKey('person.id'))
    person = relationship("PERSON", backref='family', lazy='dynamic')

    family_person_id = Column(Integer, ForeignKey('person.id'))
    family_person = relationship("PERSON", backref='family', lazy='dynamic')


class PERSON(Base):

    __tablename__ = "person"

    id = Column(Integer, primary_key=True, unique=True, autoincrement=True)
    nickname = Column(String(255))
    alias_name  = Column(String (255))
    name_normally_used = Column(String(50), nullable=False)
    first_middle_name = Column(String(255))
    last_name = Column(String(100))

创建模型时,SQLAlchemy不会引起任何问题(echo是真的,所以我可以跟踪它没有问题。)。但是,当我启动用户界面时,SQLAlchemy会抛出异常,您可以在其中管理人员的数据。

Traceback (most recent call last):
File "D:\Dan\Python\Xarphus\xarphus\subclass_master_data_load_data_item.py", line 140, in populate_item
self.populate_item_signal.emit(next(self._element))
File "D:\Dan\Python\Xarphus\xarphus\core\manage_data_manipulation_master_data.py", line 205, in select_all
for record in dict_store_session_query[category]():
File "D:\Dan\Python\Xarphus\xarphus\core\manage_data_manipulation_master_data.py", line 191, in <lambda>
'person_gender': lambda: self._session.query(PERSON_GENDER),
File "C:\Python27\lib\site-packages\sqlalchemy\orm\session.py", line 1362, in query
return self._query_cls(entities, self, **kwargs)
File "C:\Python27\lib\site-packages\sqlalchemy\orm\query.py", line 139, in __init__
self._set_entities(entities)
File "C:\Python27\lib\site-packages\sqlalchemy\orm\query.py", line 150, in _set_entities
self._set_entity_selectables(self._entities)
File "C:\Python27\lib\site-packages\sqlalchemy\orm\query.py", line 180, in _set_entity_selectables
ent.setup_entity(*d[entity])
File "C:\Python27\lib\site-packages\sqlalchemy\orm\query.py", line 3585, in setup_entity
self._with_polymorphic = ext_info.with_polymorphic_mappers
File "C:\Python27\lib\site-packages\sqlalchemy\util\langhelpers.py", line 764, in __get__
obj.__dict__[self.__name__] = result = self.fget(obj)
File "C:\Python27\lib\site-packages\sqlalchemy\orm\mapper.py", line 1948, in _with_polymorphic_mappers
configure_mappers()
File "C:\Python27\lib\site-packages\sqlalchemy\orm\mapper.py", line 2869, in configure_mappers
raise e
InvalidRequestError: One or more mappers failed to initialize - can't proceed with initialization of other mappers. Triggering mapper: 'Mapper|FAMILY|family'. Original exception was: Could not determine join condition between parent/child tables on relationship FAMILY.person - there are multiple foreign key paths linking the tables. Specify the 'foreign_keys' argument, providing a list of those columns which should be counted as containing a foreign key reference to the parent table.

Traceback (most recent call last):
File "D:\Dan\Python\Xarphus\xarphus\subclass_master_data_load_data_item.py", line 140, in populate_item
self.populate_item_signal.emit(next(self._element))
File "D:\Dan\Python\Xarphus\xarphus\core\manage_data_manipulation_master_data.py", line 205, in select_all
for record in dict_store_session_query[category]():
File "D:\Dan\Python\Xarphus\xarphus\core\manage_data_manipulation_master_data.py", line 194, in <lambda>
'person_title': lambda: self._session.query(PERSON_TITLE),
File "C:\Python27\lib\site-packages\sqlalchemy\orm\session.py", line 1362, in query
return self._query_cls(entities, self, **kwargs)
File "C:\Python27\lib\site-packages\sqlalchemy\orm\query.py", line 139, in __init__
self._set_entities(entities)
File "C:\Python27\lib\site-packages\sqlalchemy\orm\query.py", line 150, in _set_entities
self._set_entity_selectables(self._entities)
File "C:\Python27\lib\site-packages\sqlalchemy\orm\query.py", line 180, in _set_entity_selectables
ent.setup_entity(*d[entity])
File "C:\Python27\lib\site-packages\sqlalchemy\orm\query.py", line 3585, in setup_entity
self._with_polymorphic = ext_info.with_polymorphic_mappers
File "C:\Python27\lib\site-packages\sqlalchemy\util\langhelpers.py", line 764, in __get__
obj.__dict__[self.__name__] = result = self.fget(obj)
File "C:\Python27\lib\site-packages\sqlalchemy\orm\mapper.py", line 1948, in _with_polymorphic_mappers
configure_mappers()
File "C:\Python27\lib\site-packages\sqlalchemy\orm\mapper.py", line 2872, in configure_mappers
mapper._post_configure_properties()
File "C:\Python27\lib\site-packages\sqlalchemy\orm\mapper.py", line 1765, in _post_configure_properties
prop.init()
File "C:\Python27\lib\site-packages\sqlalchemy\orm\interfaces.py", line 184, in init
self.do_init()
File "C:\Python27\lib\site-packages\sqlalchemy\orm\relationships.py", line 1654, in do_init
self._setup_join_conditions()
File "C:\Python27\lib\site-packages\sqlalchemy\orm\relationships.py", line 1729, in _setup_join_conditions
can_be_synced_fn=self._columns_are_mapped
File "C:\Python27\lib\site-packages\sqlalchemy\orm\relationships.py", line 1987, in __init__
self._determine_joins()
File "C:\Python27\lib\site-packages\sqlalchemy\orm\relationships.py", line 2114, in _determine_joins
% self.prop)
AmbiguousForeignKeysError: Could not determine join condition between parent/child tables on relationship FAMILY.person - there are multiple foreign key paths linking the tables. Specify the 'foreign_keys' argument, providing a list of those columns which should be counted as containing a foreign key reference to the parent table.

我们会在那里。 SQLALchey显然有来自同一个表的两个外键的问题?问题:如何最好地进行建模以显示人与人之间的相互关系?因为在我推理之后,我需要人员表中至少有两个外键,以便在人员之间建立关系。

1 个答案:

答案 0 :(得分:1)

您对mapper类FAMILY的定义存在两个主要问题。

(1)您已将PERSON作为外键引用两次,因此您必须明确告诉SQLAlchemy如何加入PERSON,请为每个关系设置foreign_keys参数。

(2)您使用了与backref相同的值。 backrefFAMILY)的值将成为PERSON类的属性名称。查看FAMILY,有两个名为personfamily_person的属性,那么PERSON类应该有两个不同的属性。

此外,在您的代码中,FAMILY和PERSON之间的关系很多,因此dynamic值对参数lazy无效,您应该使用默认值。以下是示例代码:

class FAMILY(Base):

    __tablename__ = "family"

    id = Column(Integer, primary_key=True, unique=True, autoincrement=True)
    status = Column(String(255), nullable=False)

    person_id = Column(Integer, ForeignKey('person.id'))
    person = relationship("PERSON", backref='family_to',
                          foreign_keys=[person_id],
                          )

    family_person_id = Column(Integer, ForeignKey('person.id'))
    family_person = relationship("PERSON",
                                 foreign_keys=[family_person_id],
                                 backref='family_from')

以下是与您的问题相关的一些有用链接:Refer a table twiceRelationship configration

谢谢!