0

我一直在使用 Flask-AppBuilder 构建一个简单的 CRUD 应用程序。除了与同一个表有多个外键关系的表外,这些视图工作顺利。当我尝试对 JOINed 列进行排序时,sqlalchemy 抱怨关系混乱。

在这个应用程序中,我们有Child与两个Adults有关系:

class Adult(Model):
    adult_id = Column(Integer, primary_key=True)
    name = Column(String(50))

class Child(Model):
    child_id = Column(Integer, primary_key=True)
    name = Column(String(50))
    adult1_id = Column(Integer, ForeignKey('adult.adult_id'))
    adult2_id = Column(Integer, ForeignKey('adult.adult_id'))
    # We can also use foreign_keys to setup the relationships
    # This makes the view work (until you sort)
    adult1 = relationship("Adult", lazy='joined', backref='Adult1', primaryjoin='Adult.adult_id == Child.adult1_id')
    adult2 = relationship("Adult", lazy='joined', backref='Adult2', primaryjoin='Adult.adult_id == Child.adult2_id')

视图正确显示与孩子相关的每个成人的姓名

class ChildView(ModelView):
  datamodel = SQLAInterface(Child)
  list_columns = ['child_id', 'name', 'adult1.name', 'adult2.name']

但是当我们尝试按成人姓名排序时,我们会得到一个回溯:

InvalidRequestError: Could not find a FROM clause to join from.  Tried joining
to <class 'app.models.Adult'>, but got: Can't determine join between 'child'
and 'adult'; tables have more than one foreign key constraint relationship
between them. Please specify the 'onclause' of this join explicitly.

我可以通过一种解决方法禁用对列的排序,但我真的很想了解我缺少什么。

完整代码在这里https://github.com/cwebber314/fab_multiple_fk

追溯

Adult1.nameor排序的完整回溯Adult2.name

<snip irrelevant stuff here...>
File "c:\anaconda2\lib\site-packages\flask_appbuilder\views.py", line 475, in list
  widgets = self._list()
File "c:\anaconda2\lib\site-packages\flask_appbuilder\baseviews.py", line 877, in _list
  page_size=page_size)
File "c:\anaconda2\lib\site-packages\flask_appbuilder\baseviews.py", line 791, in _get_list_widget
  count, lst = self.datamodel.query(joined_filters, order_column, order_direction, page=page, page_size=page_size)
File "c:\anaconda2\lib\site-packages\flask_appbuilder\models\sqla\interface.py", line 94, in query
  query = query.join(model_relation)
File "c:\anaconda2\lib\site-packages\sqlalchemy\orm\query.py", line 2010, in join
  from_joinpoint=from_joinpoint)
File "<string>", line 2, in _join

File "c:\anaconda2\lib\site-packages\sqlalchemy\orm\base.py", line 201, in generate
  fn(self, *args[1:], **kw)
File "c:\anaconda2\lib\site-packages\sqlalchemy\orm\query.py", line 2154, in _join
  outerjoin, full, create_aliases, prop)
File "c:\anaconda2\lib\site-packages\sqlalchemy\orm\query.py", line 2227, in _join_left_to_right
  self._join_to_left(l_info, left, right, onclause, outerjoin, full)
File "c:\anaconda2\lib\site-packages\sqlalchemy\orm\query.py", line 2356, in _join_to_left
  "Tried joining to %s, but got: %s" % (right, ae))

InvalidRequestError: Could not find a FROM clause to join from.  Tried joining
to <class 'app.models.Adult'>, but got: Can't determine join between 'child'
and 'adult'; tables have more than one foreign key constraint relationship
between them. Please specify the 'onclause' of this join explicitly.
4

1 回答 1

0

我想我前段时间遇到了同样的问题,这很有效:

float_lenght = Column(Float)
fkey_lenght_unit = Column(Integer, ForeignKey('unitlist.id'))
unit_lenght = relationship("UnitList", foreign_keys=[fkey_lenght_unit])
float_width = Column(Float)
fkey_width_unit = Column(Integer, ForeignKey('unitlist.id'))
unit_width = relationship("UnitList", foreign_keys=[fkey_width_unit])
float_height = Column(Float)
fkey_height_unit = Column(Integer, ForeignKey('unitlist.id'))
unit_height = relationship("UnitList", foreign_keys=[fkey_height_unit])

所以也许尝试:

adult2_id = Column(Integer, ForeignKey('adult.adult_id'))
adult2 = relationship("Adult", foreign_keys=[adult2_id ])
于 2018-03-02T11:00:51.557 回答