2017-03-27 83 views
1

我有以下使用flask-sqlalchemy的sqlalchemy模型。我的時間表模型中有3個talentpref項目。總是需要有3個,不能少於3個。在SQLAlchemy中執行連接時出錯'請明確指定此連接的'onclause'。

class TalentPref(db.Model): 
    __tablename__ = 'talentpref' 
    id = db.Column(db.Integer, primary_key=True) 
    firstName = db.Column(db.String(80), unique=True) 
    lastName = db.Column(db.String(80), unique=True) 

    def __init__(self, firstName, lastName): 
     self.firstName = firstName 
     self.lastName = lastName 

    def __repr__(self): 
     return '<talentpref %r %r>' % (self.firstName, self.lastName) 

class Schedule(db.Model): 
    __tablename__ = 'schedule' 

    id = db.Column(db.Integer, primary_key=True) 

    talentpref1_id = db.Column(db.Integer, db.ForeignKey('talentpref.id')) 
    talentpref2_id = db.Column(db.Integer, db.ForeignKey('talentpref.id')) 
    talentpref3_id = db.Column(db.Integer, db.ForeignKey('talentpref.id')) 

    talentpref1 = db.relationship("TalentPref", uselist=False, foreign_keys=talentpref1_id) 
    talentpref2 = db.relationship("TalentPref", uselist=False, foreign_keys=talentpref2_id) 
    talentpref3 = db.relationship("TalentPref", uselist=False, foreign_keys=talentpref3_id) 

我正在使用flask-restless爲api資源提供調度模型。當我按計劃執行查詢並要求通過talentpref1__lastName對我的查詢進行排序時,我收到一個錯誤,這與我的多個實例引用「TalentPref」表有關:

我可以在查詢字符串上成功使用id列,就像這樣:

/api/schedule?id=id&page=1&q={"order_by":[{"field":"id","direction":"desc"}]} 

但使用以下HTTP GET查詢字符串查詢失敗:

/api/schedule?id=id&page=1&q={"order_by":[{"field":"talentpref1__lastName","direction":"desc"}]} 

有:

Traceback (most recent call last): 
    File "/Users/myuser/Documents/pythonenvironments/venv/lib/python2.7/site-packages/flask_restless/views.py", line 1172, in _search 
    result = search(self.session, self.model, search_params) 
    File "/Users/myuser/Documents/pythonenvironments/venv/lib/python2.7/site-packages/flask_restless/search.py", line 587, in search 
    query = create_query(session, model, search_params, _ignore_order_by) 
    File "/Users/myuser/Documents/pythonenvironments/venv/lib/python2.7/site-packages/flask_restless/search.py", line 549, in create_query 
    _ignore_order_by) 
    File "/Users/myuser/Documents/pythonenvironments/venv/lib/python2.7/site-packages/flask_restless/search.py", line 498, in create_query 
    query = query.join(relation_model) 
    File "/Users/myuser/Documents/pythonenvironments/venv/lib/python2.7/site-packages/sqlalchemy/orm/query.py", line 1971, in join 
    from_joinpoint=from_joinpoint) 
    File "<string>", line 2, in _join 
    File "/Users/myuser/Documents/pythonenvironments/venv/lib/python2.7/site-packages/sqlalchemy/orm/base.py", line 201, in generate 
    fn(self, *args[1:], **kw) 
    File "/Users/myuser/Documents/pythonenvironments/venv/lib/python2.7/site-packages/sqlalchemy/orm/query.py", line 2115, in _join 
    outerjoin, full, create_aliases, prop) 
    File "/Users/myuser/Documents/pythonenvironments/venv/lib/python2.7/site-packages/sqlalchemy/orm/query.py", line 2188, in _join_left_to_right 
    self._join_to_left(l_info, left, right, onclause, outerjoin, full) 
    File "/Users/myuser/Documents/pythonenvironments/venv/lib/python2.7/site-packages/sqlalchemy/orm/query.py", line 2317, 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.model.TalentPref'>, but got: Can't determine 
join between 'schedule' and 'talentpref'; tables have more than one 
foreign key constraint relationship between them. Please specify the 
'onclause' of this join explicitly. 

有沒有一種方法可以成功查詢這種關係?

+0

請包括查詢,以及在你的問題。換句話說,創建一個最小的,**完整的**和可驗證的例子。 –

+0

用http GET查詢字符串更新了帖子 – blackirishman

+0

python中的SQLAlchemy查詢。創建一個產生錯誤的自包含示例。 –

回答

2

這似乎是flask-restless本身的限制。當通過<字段名>的形式< relationname> __ < fieldname>它會split the name and use the 1st part as the relationship。它使用關係屬性來查找相關的模型類加入到:

if '__' in field_name: 
    field_name, field_name_in_relation = \ 
     field_name.split('__') 
    relation = getattr(model, field_name) 
    relation_model = relation.mapper.class_ 
    field = getattr(relation_model, field_name_in_relation) 
    direction = getattr(field, val.direction) 
    query = query.join(relation_model) 
    #     ^^^^^^^^^^^^^^ TalentPref model class 
    query = query.order_by(direction()) 

https://github.com/jfinkels/flask-restless/blob/0.17.0/flask_restless/search.py#L498

在你的情況,這是有效

query = query.join(TalentPref) 

因爲你有multiple join paths,SQLAlchemy的是無法確定要做什麼。如果燒瓶不安靜地使用simple relationship join而不是加入目標實體,或者將relationship()驅動的ON子句修改爲目標實體,則這不是問題。

你可以修補燒瓶蠢蠢欲動,想要解決這個特定的查詢:

--- search.py 2017-03-29 09:56:00.439981932 +0300 
+++ search_joinfix.py 2017-03-29 09:56:41.375851375 +0300 
@@ -495,7 +495,7 @@ 
         relation_model = relation.mapper.class_ 
         field = getattr(relation_model, field_name_in_relation) 
         direction = getattr(field, val.direction) 
-      query = query.join(relation_model) 
+      query = query.join(relation) 
         query = query.order_by(direction()) 
        else: 
         field = getattr(model, val.field)