使Flask-AppBuilder与具有多个外键的表的视图很好地配合

时间:2017-08-05 22:04:40

标签: python flask-sqlalchemy flask-appbuilder

我一直在玩,使用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.nameAdult2.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.

1 个答案:

答案 0 :(得分: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 ])