2016-11-24 201 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