【问题标题】:Update random row in DB using Flask-Sqlalchemy使用 Flask-Sqlalchemy 更新数据库中的随机行
【发布时间】:2017-04-08 05:56:29
【问题描述】:

我一直在尝试使用 Flask 和 Flask-Sqlalchemy 更新我的 Sqlite 数据库中随机选择的行。我在数据库中只有几行名为“word”、“yes”和“no”的列,其中 word 是一个字符串,yes 和 no 是整数。 “投票”视图上有两个按钮,是和否。当按下按钮时,相应的代码会执行,应该增加 yes 或 no 列,并使用 Word 表中的新随机词更新视图。

@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

保存在会话对象中,但仅在下次查询该数据库行时才提交。当我将方法顶部的查询替换为:

row = Word.query.get(4)

返回 id 为 4 的行。使用此查询,yes 或 no 列会立即更新。

有什么想法吗?

谢谢

【问题讨论】:

  • 您的增量容易受到竞争条件的影响。您应该让数据库为您处理增量。 row.yes = Word.yes + 1

标签: sqlite python-3.x flask sqlalchemy flask-sqlalchemy


【解决方案1】:

谢谢大家。我解决了这个问题。数据库递增实际上工作正常,但我没有递增正确的行。问题是我在每次调用 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

【讨论】:

    【解决方案2】:

    我认为您需要在提交之前将更新添加到会话中,使用如下代码:

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

    这是我在 Flask-SQLAlchemy 中用于基本更新的模式。

    【讨论】:

    • 如果它们是通过它加载的,您不需要将它们添加到会话中。 Model.query 这样做。
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 2018-09-06
    • 1970-01-01
    • 1970-01-01
    • 2017-12-15
    • 1970-01-01
    • 1970-01-01
    • 2014-07-19
    相关资源
    最近更新 更多