2016-11-24 63 views
2

我一直在嘗試使用Flask和Flask-Sqlalchemy來更新我的Sqlite數據庫中隨機選擇的一行。我在數據庫中只有幾行,名爲「word」,「yes」和「no」,其中word是一個字符串,yes和no是整數。 「投票」視圖上有兩個按鈕,是和否。當按下按鈕時,執行相應的代碼,應增加「是」或「否」列,並使用Word表中新的隨機單詞更新視圖。使用Flask-Sqlalchemy更新數據庫中的隨機行

@app.route("/vote", methods=["GET", "POST"]) 
def vote(): 
    #Get random row from database 
    query = db.session.query(Word) 
    rowCount = int(query.count()) 
    row = query.offset(int(rowCount*random.random())).first() 

    #POST 

    # If "yes" button is pressed, increment yes column in database 
    if request.method == "POST": 
     if request.form.get("yes"): 
      row.yes += 1 
      db.session.commit() 
      return render_template("vote.html", row=row) 
    # otherwise increment no column 
     elif request.form.get("no"): 
      row.no += 1 
      db.session.commit() 
      return redirect(url_for("vote")) 

    #GET 

    # on get request, render vote.html 
    return render_template("vote.html", row=row) 

此代碼正在工作,但yes和no列僅在視圖下次回到隨機單詞時更新。如果我點擊一個按鈕後立即關閉瀏覽器,數據庫不會增加。我認爲這與db.session.commit()有關,或者與會話有關。這似乎是:

row.yes += 1 

被保存在session對象,但只是承諾當數據庫行查詢的下一次。此代碼沒有工作時,我更換了查詢在方法的頂部:

row = Word.query.get(4) 

返回與4號列與該查詢中,是或否柱立即更新。

有什麼想法?

感謝

+0

您的增量容易受到競爭條件的影響。你應該讓數據庫爲你處理增量。 'row.yes = Word.yes + 1' – dirn

回答

2

謝謝大家。我解決了這個問題。數據庫增量實際上工作正常,但我沒有遞增正確的行。問題是,我在vote()方法的每次調用時都從數據庫生成了一個隨機行,這意味着我得到了一個GET請求的隨機值,以及POST請求的一個不同的隨機值,並最終增加了POST請求中的不同隨機值。

我把邏輯分成兩個方法用於「/ vote」路由,getWord()和vote(),併爲行生成創建了randRow()方法。我需要存儲調用getWord()時生成的隨機行,因此我使用了會話變量,以便可以從vote()方法訪問隨機行。這有點冗長,但似乎工作。

任何人都有更好的想法如何實現這一目標?

@app.route('/vote', methods=["GET"]) 
def getWord(): 
    wordObj = randRow() 
    session['word'] = wordObj.word 
    session['yesVotes'] = wordObj.yes 
    session['noVotes'] = wordObj.no 
    return render_template("vote.html", word=session['word'], yesVotes=session['yesVotes'], noVotes=session['noVotes']) 

@app.route('/vote', methods=["POST"]) 
def vote(): 
    # store session 'word' in word variable 
    # look up word in database and store object in wordObj 
    word = session['word'] 
    wordObj = Word.query.filter_by(word=word).first() 
    # check button press on vote view, increment yes or no column 
    # depending on which button was pressed 
    if request.form.get("yes"): 
     wordObj.yes = wordObj.yes + 1 
    elif request.form.get("no"): 
     wordObj.no = wordObj.no + 1 
    db.session.commit() 
    return redirect(url_for("getWord")) 

###### HELPERS ###### 

# returns a random row from the database 
def randRow(): 
    rowId = Word.query.order_by(func.random()).first().id 
    row = Word.query.get(rowId) 
    return row 
0

我認爲你需要之前更新添加到會話提交,使用這樣的代碼:

[...] 
    row.yes += 1 
    db.session.add(row) 
    db.session.commit() 
[...] 

這是我用在燒瓶SQLAlchemy的一個基本的更新模式。

+0

如果通過它加載,則不需要將內容添加到會話中。 'Model.query'就是這樣。 – dirn