2013-10-22 43 views
2

目前我有一個表在我的數據庫id,名稱(str),和數據(int)列。還有就是選擇一個按鈕,增加了1到數據庫中的相應條目的HTML單選按鈕形式:從sqlite3數據庫表單提交sqlalchemy行更新不一致行爲

length_table=session.query(func.count(Item.id)).scalar() 
randoms=random.sample(range(length_table),2) 
item1=session.query(Item).filter_by(id=randoms[0]+1).one() 
item2=session.query(Item).filter_by(id=randoms[1]+1).one() 

if request.POST.get('myradiobutton') == "left": 
    item1.data+=1 
    return HTTPFound(location=request.route_url('sorting')) 

if request.POST.get('myradiobutton') == "right": 
    item2.data+=1 
    return HTTPFound(location=request.route_url('sorting')) 

這工作,但它也有一些以次充好的行爲(有時會添加到右側的項目,有時增加了錯誤的項目)。因爲我正在使用pyramid_tm應該處理提交。 SQL日誌給我:

SELECT rowid, * FROM items ORDER BY rowid; 
SELECT name, sql FROM sqlite_master WHERE type='table' ; 
PRAGMA TABLE_INFO(items); 
SELECT name, sql FROM sqlite_master WHERE type='index' 

沒有更新聲明,這對我來說很陌生。如果非數據庫發佈,數據庫如何更新?我相信更新應該在transaction.commit()行上進行。

下面是表的定義:

class Item(Base): 
    __tablename__ = 'items' 
    id = Column(Integer, primary_key=True) 
    name = Column(Text, unique=True) 
    data = Column(Integer) 

    def __init__(self, name, data): 
     self.name = name 
     self.data = data 

這是發動機創建:

def main(argv=sys.argv): 
    if len(argv) != 2: 
     usage(argv) 
    config_uri = argv[1] 
    setup_logging(config_uri) 
    settings = get_appsettings(config_uri) 
    engine = engine_from_config(settings, 'sqlalchemy.') 
    DBSession.configure(bind=engine) 
    Base.metadata.create_all(engine) 
+2

我不明白:你正在做隨機生成的數字過濾,並想知道爲什麼你的代碼有非確定性的行爲。但我並沒有真正理解代碼,不能完全評論發生了什麼。 –

+0

是的,它的奇怪。我試過http:// stackoverflow。COM /問題/ 19507467 /何燦我選-2不同,隨機行從 - 一個表,但是你可以看到我爲什麼改變了它 – BigBoy1337

+0

只輸出正在運行看實際的SQL查詢你」重新發送到數據庫。然後將該查詢與數據庫中的數據進行比較。答案將是非常明顯的 –

回答

0

確定這是問題。當我第一次調用item1和item2時,它會隨機查詢數據庫中隨機的隨機整數,這些隨機整數在randoms中制定。

但是當它到達item1.data+=1行時,它會嘗試並隨機查詢item1。這意味着無論輸出是什麼(右邊或左邊),它會再次從數據庫中隨機選擇一個項目以添加1到。也就是不一致的結果。

爲了解決這個問題,我不得不將我的代碼分離到GET和POST案例中,如下所示。基本上,我在頁面最初加載時在GET方法中創建了兩個隨機「鍵」。然後,我通過了鑰匙模板

if request.method == "GET": 


     length_table=session.query(func.count(Item.id)).scalar() 
     randoms=random.sample(range(1,length_table+1),2) 


     results = session.query(Item).filter(Item.id.in_(randoms)).all() 


     return {'randoms':randoms,'item1':randoms[0],'item2':randoms[1],'results':results} 

然後在模板上,我把這些鍵值到表單,用戶提交的隱藏價值

<input type="hidden" name="item1" value=${item1}> 
<input type="hidden" name="item2" value=${item2}> 

最後,在後一部分,我拉在那些價值觀中。這意味着它們不會被重新隨機化,而是與原始項目被查詢的關鍵值相同。

if request.method == "POST": 

     key1=request.params['item1'] 
     key2=request.params['item2'] 
     randoms=[key1,key2] 
     results = session.query(Item).filter(Item.id.in_(randoms)).all() 
     if output == "left": 
      results[0].data=results[0].data+1 

      return HTTPFound(location=request.route_url('sorting')) 

     if output == "right": 
      results[1].data=results[1].data+1 
      return HTTPFound(location=request.route_url('sorting')) 
2

我不能完全確定您的item1item2是從哪裏來的,但我假設你在發佈邏輯之前將它們初始化了某處,例如:

item1 = DBSession.query(Item).filter(Item.id == passed_value).first() 

如果不是,item1item2是什麼?

無論如何,假設你已經有一個有效的item1對象,並希望更新它,你使用ZopeTransactionExtension我最終會做這樣的事情:

if request.POST.get('myradiobutton') == "left": 
    item1.data+=1 
    DBSession.add(item1) 
    DBSession.flush() 
    return HTTPFound(location=request.route_url('sorting')) 
+0

在刷新提交更改之前,我應該將該項目添加到數據庫會話是有意義的。但是,您的解決方案似乎無法解決問題。因爲我正在使用金字塔框架,我聽說我需要使用transaction.commit(),儘管我不完全明白爲什麼。此外,我已將項目定義添加到問題中,以便您可以看到它們。 – BigBoy1337

+0

謝謝!我對金字塔也相對陌生,但我認爲只有在您不使用ZopeTransactionExtension時才需要transaction.commit();我公司以[從金字塔網站教程]上幾乎一切(http://docs.pylonsproject.org/projects/pyramid/en/1.4-branch/tutorials/wiki2/definingmodels.html#making-edits-to-models- PY)。類似於'DBSession = scoped_session(sessionmaker(extension = ZopeTransactionExtension()))'在你的模型聲明中。 –