2013-10-10 65 views
0

我使用flask-sqlalchemy發表了此聲明,並且我已選擇將其保留原始格式。 Post.query相當於session.query(Post)Sqlalchemy篩選條件在子查詢中始終返回True

我試圖做一個子查詢來過濾出數據庫中所有處於草稿狀態並且不是由當前用戶創建或修改的帖子。我做了這個查詢,

Post.query\ 
    .filter(sqlalchemy.and_(
     Post.post_status != Consts.PostStatuses["Draft"], 
      sqlalchemy.or_(
       Post.modified_by_id == current_user.get_id(), 
       Post.created_by_id == current_user.get_id())) 

這創造:

Where true AND ("Post".modified_by_id = :modified_by_id_1 OR 
"Post".created_by_id = :created_by_id_1) 

預期的結果:

Where "Post".post_status != "Draft" AND (
"Post".modified_by_id = :modified_by_id_1 OR 
"Post".created_by_id = :created_by_id_1) 

我想知道,爲什麼會這樣?我如何增加SQLAlchemy中的錯誤級別?我認爲我的項目正在悄然失敗,我想確認我的猜測。

更新:

我使用了錯誤的常數字典。一個字典包含整數,另一個包含字符串(一個用於數據庫查詢,一個用於打印)。

_post_status = db.Column(
     db.SmallInteger, 
     default=Consts.post_status["Draft"]) 

post_status包含整數,Consts.PostStatuses包含字符串。後視,真是糟糕的主意。我將製作一個返回一個元組而不是兩個字典的單個字典。

@property 
def post_status(self): 
    return Consts.post_status.get(getattr(self, "_post_status", None)) 
+0

Post.post_status和Consts.PostStatuses是什麼類型[「草稿」]?是發佈模型嗎? SqlAlchemy基於類型和python魔術方法構建查詢。我可以告訴你,如果post_status是布爾型並且draft是空字符串,sqlalchemy將生成一個總是true的sql語句。當然還有其他的情況。 –

+0

post_status是一個小型int,PostStatuses是一個int(在這種情況下爲1)。 – AlexLordThorsen

+0

你能更精確嗎?在運行查詢之前,添加一個「打印類型(Post.post_status)」,鍵入(Const.PostStatuses [「Draft」])''。它應該打印類似' int' – SingleNegationElimination

回答

2

的問題是,你的財產post_status不是在ORM級查詢使用可以接受的,因爲這是一個python descriptor它在默認情況下返回自己的一流水平:

from sqlalchemy import * 
from sqlalchemy.orm import * 
from sqlalchemy.ext.declarative import declarative_base 

Base = declarative_base() 

class A(Base): 
    __tablename__ = 'a' 

    id = Column(Integer, primary_key=True) 

    _post_status = Column(String) 

    @property 
    def post_status(self): 
     return self._post_status 


print (A.post_status) 
print (A.post_status != 5678) 

輸出:

$ python test.py 
<property object at 0x10165bd08> 
True 

你正在尋找的使用類型似乎是一個hybrid attribute,這是一個SQLAlchemy的,包括擴展到「REG的ular」巨蟒描述符中產生類級別的行爲與核心SQL表達式兼容:

from sqlalchemy.ext.hybrid import hybrid_property 

class A(Base): 
    __tablename__ = 'a' 

    id = Column(Integer, primary_key=True) 

    _post_status = Column(String) 

    @hybrid_property 
    def post_status(self): 
     return self._post_status 

print (A.post_status) 
print (A.post_status != 5678) 

輸出:

$ python test.py 
A._post_status 
a._post_status != :_post_status_1 

務必仔細閱讀混合文檔仔細包括how to establish the correct SQL expression behavior,即在工作既描述實例和類級別是一種有點高級的Python技術。

+0

我最終只是測試'_post_status'而不是屬性'post_status'。這聽起來像是更好的解決方案。 – AlexLordThorsen