我一直在使用 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.name
or排序的完整回溯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.