2016-11-24 8 views
2

FlaskとFlask-Sqlalchemyを使用して、Sqliteデータベース内のランダムに選択された行を更新しようとしています。私は "word"、 "yes"、 "no"という列を持つデータベースにほんのいくつかの行を持っています。wordは文字列、yesとnoは整数です。 「投票」ビューには、はいといいえの2つのボタンがあります。ボタンを押すと、適切なコードが実行され、yesまたはnoの列がインクリメントされ、Wordテーブルの新しいランダムな単語でビューが更新されます。Flask-Sqlalchemyを使用してDB内のランダムな行を更新します。

@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) 

このコードは動作していますが、ビューは、ランダムな単語次回に周りに戻って来るときイエスとノーの列にのみ更新されます。ボタンをクリックした直後にブラウザを閉じると、データベースはインクリメントされません。私はこれがdb.session.commit()やセッションに関するものと関係があると思います。

row.yes += 1 

はセッションオブジェクトに保存されますが、そのデータベース行が次に照会されるときにのみコミットされます。 yesまたはno列が即座に更新され、このクエリでは4のIDを持つ行を返す

row = Word.query.get(4) 

:私はメソッドの先頭にクエリを交換したときにこのコードは、仕事をしました。

どのような考えですか?私はフラスコSQLAlchemyの中の基本的な更新のために使用したパターンだ

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

おかげ

+0

あなたの増分は競合状態に脆弱です。データベースがあなたのためにインクリメントを処理するようにする必要があります。 'row.yes = Word.yes + 1' – dirn

答えて

2

ありがとうございます。私は問題を理解した。データベースの増分は実際にうまくいきましたが、私は正しい行を増やしていませんでした。問題は、vote()メソッドの呼び出しごとにデータベースからランダムな行を生成したことです。これは、GETリクエストのランダムな値とPOSTリクエストの別のランダムな値が得られたことを意味し、 POST要求の異なるランダム値。

私はロジックを "/ vote"ルートの2つのメソッド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

私はあなたがこのようなコードを使用して、コミットする前にセッションにアップデートを追加する必要があると思います。

+0

セッションにロードされたものをセッションに追加する必要はありません。 'Model.query'はそれを行います。 – dirn

関連する問題