🎄teratailクリスマスプレゼントキャンペーン2024🎄』開催中!

\teratail特別グッズやAmazonギフトカード最大2,000円分が当たる!/

詳細はこちら
Flask

FlaskはPython用のマイクロフレームワークであり、Werkzeug・Jinja 2・good intentionsをベースにしています。

SQLite

SQLiteはリレーショナルデータベース管理システムの1つで、サーバーではなくライブラリとして使用されている。

POST

POSTはHTTPプロトコルのリクエストメソッドです。ファイルをアップロードしたときや入力フォームが送信されたときなど、クライアントがデータをサーバに送る際に利用されます。

HTML

HTMLとは、ウェブ上の文書を記述・作成するためのマークアップ言語のことです。文章の中に記述することで、文書の論理構造などを設定することができます。ハイパーリンクを設定できるハイパーテキストであり、画像・リスト・表などのデータファイルをリンクする情報に結びつけて情報を整理します。現在あるネットワーク上のほとんどのウェブページはHTMLで作成されています。

Q&A

解決済

1回答

720閲覧

[HTML, Flask] GETの後のPOST時にGETの時の表示 (変数) を保ったままにしたい

Yukiya025

総合スコア86

Flask

FlaskはPython用のマイクロフレームワークであり、Werkzeug・Jinja 2・good intentionsをベースにしています。

SQLite

SQLiteはリレーショナルデータベース管理システムの1つで、サーバーではなくライブラリとして使用されている。

POST

POSTはHTTPプロトコルのリクエストメソッドです。ファイルをアップロードしたときや入力フォームが送信されたときなど、クライアントがデータをサーバに送る際に利用されます。

HTML

HTMLとは、ウェブ上の文書を記述・作成するためのマークアップ言語のことです。文章の中に記述することで、文書の論理構造などを設定することができます。ハイパーリンクを設定できるハイパーテキストであり、画像・リスト・表などのデータファイルをリンクする情報に結びつけて情報を整理します。現在あるネットワーク上のほとんどのウェブページはHTMLで作成されています。

0グッド

0クリップ

投稿2019/09/29 08:10

編集2019/10/02 07:51

現在の挙動

現在0番の問題が出るようにapp.pydo_f()関数内で指定しています。しかし、文法問題は6つ (0~5番)あるので、「делатьの現在活用」の「練習する」をクリックする度にランダムに問題を表示するようにしたいです。

関係するファイル

  • app.py
  • templates/verb/do_f.html
  • ru_func.py
  1. делатьの現在活用を開き、「練習する」をクリック。

d1
2. делаюと打ちEnterまたは[解答する]をクリック。
d2
3. 「正解!<делаю>です。」と判定結果が出る (違う単語を入力すれば「正解は <делаю> です。もう一度してみてね」と出る)
d3

現在の挙動の問題点

ramdom.randient(0, 5)app.pydo_f()関数(通し番号23~25行目あたり) に挿入すればよいかと思ったのですが、単語を打ち込み[解答する]をクリックすると、ramdom.randient(0, 5)がもう一度動くようで、正解かどうかを新しく表示された単語と照合し、「正解は <xxxx> です。もう一度してみてね」となります。「練習する」をクリックしたときに出る値を保ってそれと照合するにはどうしたらよいでしょうか?

文法問題一覧とrandam.randient()にした場合の挙動

データベースはSQLiteです。一番最後のдела~と入力値を照合し正解かどうかを判定します。
しかしramdom.randient(0, 5)app.pydo_f()関数(通し番号23~25行目) に挿入すると。。。

  1. Я <ここに入力> всё что хочу.делаюと入力し[解答する]を押す。
  2. なぜかまたramdom.randient(0, 5)が働き、例えば5|Они|уроки на английском.|1|делаютが表示&делаютと照合され「正解は <делают> です。もう一度してみてね」となります。

SQL

10|Я|всё что хочу.|1|делаю 21|Ты|этот мир лучше.|1|делаешь 32|Что он|сейчас?|1|делает 43|Мы|глупые селфи.|1|делаем 54|Это вы|весной.|1|делаете 65|Они|уроки на английском.|1|делают

関係リソース

  • GitHub
  • heroku 実際に挙動を確認できます。ただし現在問題文はランダムではなく0固定。

アドバイスでquestion_noなど追加 (2019/10/01追記)

FiroProchainezoさまのアドバイスでquestion_noなど追加しましたが、挙動変わらず。でもdo_fp(question_no)のように関数に変数渡して。。。というのは私では思いつきませんでした(≧∀≦)

問題と解答の照合が+1ずつずれる問題

そこで思い至ったのですが、もしделатьの現在活用のページでこっそりと乱数question_noを生成し、それをverb/do_fverb/do_f/int:question_noと渡せればずれが是正されるのではと考え始めました。が、こっそりと乱数question_noを生成し、次のページに渡していく。。。という仕様が思いつきません(T_T)**「こっそり(ページ上では見えないように)」**という部分が難しいです。

SQL

10|Я|всё что хочу.|1|делаю 21|Ты|этот мир лучше.|1|делаешь 32|Что он|сейчас?|1|делает 43|Мы|глупые селфи.|1|делаем 54|Это вы|весной.|1|делаете 65|Они|уроки на английском.|1|делают

現状例えば上記の並びで乱数が生成されるとすると、1番の答えが2番(делает)と照合され、2番の答えが3番(делаем)と照合され。。。となります。

できましたー(≧∀≦)(2019/10/02追記)

FiroProchainezoさまのアドバイス:

sessionを使うか、postにhidden属性で入れて渡すかのどちらか

sessionを使うことにし、app.pyのdef verb():session['secret_text'] = random.randint(0, 5)を追加→app.pyのdef do_f():question_no = session['secret_text']を入れるとズレが解消されました!ありがとうございます<3
他の問題を出すには前のページに戻る必要があるのでdo_fページに戻るための戻って[練習する]ボタンを再度クリックボタンも追加しました!遊んでみてください<3

気になる質問をクリップする

クリップした質問は、後からいつでもMYページで確認できます。

またクリップした質問に回答があった際、通知やメールを受け取ることができます。

バッドをするには、ログインかつ

こちらの条件を満たす必要があります。

guest

回答1

0

ベストアンサー

こんなのはどうでしょう。
(結合して動作確認はしていないので、確認お願いします。)
randomに値を作ってそれを使ってしまうと、毎回値が変わって困る、ようなので、randomに値を作って、postされた画面ではその値を覚えていて使い回す、というように変えると良いと思います。

  1. randomに値を作る
  2. 作った値をtemplateに渡す
  3. templateから「選ばれているquestionの番号を渡す」ように変更する
  4. do_fp()で値を受け取れるようにする。
  5. do_fo()でpostした場合にも、「選ばれているquestionの番号を渡す」ように変更する
  6. 対応した質問と回答を持ってくるようにする
    (ru_funcの呼び出しを変更する?)

python

1# app.py:do_f() 2 # 1. randomに値を作る 3 question_no = random.randint(0.5) 4 5 # 2. 作った値をtemplateに渡す 6 if request.method == 'GET': 7 return render_template('verb/do_f.html', 8 ex0=ex0, 9 ex1=ex1, 10 question_no=question_no 11 ) 12

html

1<!-- do_f.html --> 2 3 <!-- 3. templateから「選ばれているquestionの番号を渡す」ように変更する --> 4 <form method="post" action="{{ url_for('do_f') }}/{{ question_no }}"> 5

python

1# app.py:do_fp() 2 3# 4. do_fp()で値を受け取れるようにする。 4@app.route('/verb/do_f/<int:question_no>', methods=['POST']) 5def do_fp(question_no): 6 7# 5. do_fo()でpostした場合にも、「選ばれているquestionの番号を渡す」ように変更する 8 if get3 == form_input: 9 return render_template('verb/do_f.html', 10 ex0=get1, 11 ex1=get2, 12 form_input="正解!<" + get3 + ">です。", 13 question_no=question_no) 14 else: 15 return render_template('verb/do_f.html', 16 ex0=get1, 17 ex1=get2, 18 form_input="正解は <" + get3 + "> です。もう一度してみてね。", 19 question_no=question_no) 20 21

以下余談

IDEで開いた時にいろいろ指摘が表示されるので、変更下法が良いと思います。

html要素にはlang属性を設定しましょう。

html

1<html> 2<!-- ↓ --> 3<html lang="ja">

title要素を追加しましょう。

<head>内に<title>が必要です。

idはユニークにしましょう。

russian.htmlでid=="grammardoor"が複数存在します。
idはユニークでなければならないため、複数の要素に同じ名前を付けたい場合はclassを利用しましょう。

<input id = "grammardoor" onclick="location.href='verb'" value="動詞"> ^^^^^^^^^^^ <input id = "grammardoor" onclick="location.href='verb'" value="名詞"> <!--hrefはダミーだよ!変えてね--> ^^^^^^^^^^^ <!-- ↓ --> <input class = "grammardoor" onclick="location.href='verb'" value="動詞"> <input class = "grammardoor" onclick="location.href='verb'" value="名詞"> <!--hrefはダミーだよ!変えてね-->

理由がないならinputではなくaを使いましょう。

別ページに移動したいだけなら、input要素を使う意味が無いと思います。
a要素を使うのが一般的です。

html

1<input class = "grammardoor" onclick="location.href='verb'" value="動詞"> 2 3<!-- ↓ --> 4<a href="verb">動詞</a>

PEP8に対応しましょう。

全部かはわかりませんが、app.pyでは@app.route()の上に1行しか空いていません。
PEP8では、@app.route(関数)の上に2行のブランクが必要です。
(コーディング規則に従うと、他人が見やすくなります)

jinja2のコメントについて。

jinja2では{# #}でコメントを記載することができます。
htmlのコメントは、ブラウザからソースを見ると見えてしまいますが、jinja2のコメントは見えません。
開発時のメモ等はjinja2のコメントを使った方が良いでしょう。

html

1<!-- htmlのコメント --> 2{# jinja2のコメント #}

col要素について。

base_verb_p.htmlに空の<col>要素が並んでいますが、確認したところ、<colgroup>要素の中でしか使えない要素のようです。
不要なら削除し、必要なら<colgroup>要素の中に入れましょう。

url以外の方法(2019/10/02 10:55追記)

urlに値を入れる以外で他のページに渡すとしたら、sessionを使うか、postにhidden属性で入れて渡すかのどちらかと思います。
以下、サンプルです。

python

1# app.py 2from flask import Flask, session, render_template, request 3 4app = Flask(__name__) 5app.secret_key = 'secret key' 6 7 8@app.route('/') 9def index(): 10 session['secret_text'] = 'secret_text session' 11 return render_template('index.html') 12 13 14@app.route('/session_test') 15def session_test(): 16 secret_text = session['secret_text'] 17 return secret_text 18 19 20@app.route('/post_test', methods=['POST']) 21def post_test(): 22 secret_text = request.form['secret_text'] 23 24 return secret_text 25 26 27if __name__ == '__main__': 28 app.run(host='0.0.0.0', port=5000) 29

html

1<!-- templates/index.html --> 2<!DOCTYPE html> 3<html lang="ja"> 4<head> 5 <meta charset="UTF-8"> 6 <title>Test Page</title> 7</head> 8<body> 9 <div> 10 <h2>フォームを使う</h2> 11 <form action="{{ url_for('post_test') }}" method="POST"> 12 <label for="visible_text">見える入力項目</label> 13 <input type="text" name="visible_text" id="visible_text"> 14 <input type="hidden" value="secret value post" name="secret_text" id="secret_text"> 15 <input type="submit" value="入力する"> 16 </form> 17 </div> 18 <div> 19 <h2>フォームは使わない</h2> 20 <a href="{{ url_for('session_test') }}">他のページへ</a> 21 </div> 22</body> 23</html>

投稿2019/09/30 07:24

編集2019/10/02 01:58
FiroProchainezo

総合スコア2421

バッドをするには、ログインかつ

こちらの条件を満たす必要があります。

Yukiya025

2019/10/01 05:11 編集

FiroProchainezoさまありがとうございます!挙動は変わらなかったのですが、経過を質問文末尾に追加しました。 こっそり(ページ上では見えないように)乱数を生成し、こっそりそれを他の関数に渡す方法、ご存じですか。。。? あと記法上の注意もありがとうございました(≧∀≦) IDEであればそんな警告が出るのですね!
Yukiya025

2019/10/02 07:52

できましたー!ありがとうございます<3 顛末を質問末尾に追記したのでご覧ください^^/
guest

あなたの回答

tips

太字

斜体

打ち消し線

見出し

引用テキストの挿入

コードの挿入

リンクの挿入

リストの挿入

番号リストの挿入

表の挿入

水平線の挿入

プレビュー

15分調べてもわからないことは
teratailで質問しよう!

ただいまの回答率
85.36%

質問をまとめることで
思考を整理して素早く解決

テンプレート機能で
簡単に質問をまとめる

質問する

関連した質問