質問をすることでしか得られない、回答やアドバイスがある。

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

新規登録して質問してみよう
ただいま回答率
85.48%
Flask

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

HTML5

HTML5 (Hyper Text Markup Language、バージョン 5)は、マークアップ言語であるHTMLの第5版です。

Python

Pythonは、コードの読みやすさが特徴的なプログラミング言語の1つです。 強い型付け、動的型付けに対応しており、後方互換性がないバージョン2系とバージョン3系が使用されています。 商用製品の開発にも無料で使用でき、OSだけでなく仮想環境にも対応。Unicodeによる文字列操作をサポートしているため、日本語処理も標準で可能です。

Q&A

解決済

1回答

2630閲覧

【Jinja2】python+flaskを使った開発。コンソール上では表示されるデータが、HTML上で表示できない。

yujin1202

総合スコア56

Flask

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

HTML5

HTML5 (Hyper Text Markup Language、バージョン 5)は、マークアップ言語であるHTMLの第5版です。

Python

Pythonは、コードの読みやすさが特徴的なプログラミング言語の1つです。 強い型付け、動的型付けに対応しており、後方互換性がないバージョン2系とバージョン3系が使用されています。 商用製品の開発にも無料で使用でき、OSだけでなく仮想環境にも対応。Unicodeによる文字列操作をサポートしているため、日本語処理も標準で可能です。

0グッド

0クリップ

投稿2021/05/01 06:49

編集2021/05/06 00:10

<後記、2021年5月6日> 
全体像として、何をやりたかったを、Githubに記載しました。
宜しかったら、眺めてください。改めて、皆さま、ありがとうございました。
https://github.com/kazu0116/web_application

=====================

HTMLと言うか、Jinja2の書き方の問題と言う気がするのですが、どうしても分かりません。
教えてください。

<背景>
Python Flaskを使用して、DB(mysql)サーバから、データを引っ張ってきて、HTMLに表示すると言う、下記の様なシステムを開発しております。

1)ユーザーは、HTML(index.html)上で、旅行したい国のチェックボックスにチェックを入れて(複数選択も可)、送信ボタンをクリックする。
![イメージ説明

2)選択された国の旅行情報を、DBから引っ張ってきて、コンソール上に表示すると共に、HTML(index1.html)に表示する。

<説明>
試行錯誤した結果、pythonの方は、下記の様なコードにたどり着きました。

from flask import Flask, render_template,request import pymysql app = Flask(__name__) @app.route('/', methods=['GET']) def get(): return render_template('index.html', \ title = 'Form Sample(get)', \ message = 'Where do you want to go?') def getConnection(): return pymysql.connect( host='localhost', db='first_db', user='root', password='password', charset='utf8', cursorclass=pymysql.cursors.DictCursor ) @app.route('/', methods=['POST']) def select_sql(): connection = getConnection() message = "test" names = request.form.getlist('checkbox') for name in names: cursor = connection.cursor() sql = "select Country, Agency, email from tb3 where Country=%s"; cursor.execute(sql, (name,)) list1s = cursor.fetchall() #TakaiYさんのコメントを受け、誤字修正 print(list1) #コンソール上での動作確認用 cursor.close()   connection.close()  return render_template( 'index1.html', list1s = list1s)  if __name__ == '__main__': app.run()

コンソール上への表示は、1つの国を選択した場合も、複数の国を選択した場合も、期待した通りのデータを返してきます。(ここまでは、OK。下記は、3か国を選択した場合のコンソール表示。)

<コンソール上では表示される>
[{'Country': 'Australia', 'Agency': 'DEF Travel', 'email': '456@yahoo.com'}]
[{'Country': 'England', 'Agency': 'GHI Travel', 'email': '789@hotmail.com'}]
[{'Country': 'France', 'Agency': 'JFK Travel', 'email': '1111@yahoo.co.jp'}]

<質問>
上記の様に、コンソール上には、問題なく表示されておりますが、HTML上で表示が上手くいきません。
(複数項目を選択した場合、最後にチェックした国(上記の例では、フランス)しか、HTML上で表示できません。)

<HTML(index1.html)上の表示>
イメージ説明

<index1.htmlのコードは下記>

<!doctype html> <html lang="ja"> <head> <meta charset="utf-8"> <meta name="viewport" content="width=device-width, initial-scale=1, shrink-to-fit=no"> <title>test_list</title> </head> <body> <h1>{{ title }}</h1> {% block content %} {% for list1 in list1s %} <p>{{list1}}</p> {% endfor %} {% endblock %} --!> </form> </body> </html>

複数項目を表示(HTML上に)させる為には、HTML(index1.html)をどの様に書けば良いのでしょうか?
丸2日間、色々と試したのですが、どうしても上手くいきません。
よろしくお願いいたします。

************
2021年5月3日、TakaiYさんのアドバイスに基づき、解決しております。
最終コードは下記です。(御参考まで)

  1. pythonのコード
from flask import Flask, render_template,request import pymysql app = Flask(__name__) @app.route('/', methods=['GET']) def get(): return render_template('index.html', \ title = 'Form Sample(get)', \ message = 'Where do you want to go?') def getConnection(): return pymysql.connect( host='localhost', db='first_db', user='root', password='yireozna', charset='utf8', cursorclass=pymysql.cursors.DictCursor ) @app.route('/', methods=['POST']) def select_sql(): connection = getConnection() message = "test" names = request.form.getlist('checkbox') list1s=[] for name in names: cursor = connection.cursor() sql = "select Country, Agency, email from tb3 where Country=%s"; cursor.execute(sql, (name,)) list = cursor.fetchall() list1s.append(list1) cursor.close() connection.close() print(list1s) #コンソール上で、キチンとデータが取得できているかどうかの確認用 return render_template( 'index1.html', list1s = list1s) if __name__ == '__main__': app.run()

2.index.htmlのコード

<!doctype html> <html lang="ja"> <head> <meta charset="utf-8"> <meta name="viewport" content="width=device-width, initial-scale=1, shrink-to-fit=no"> <title>Hello World</title> </head> <body> <h1>{{ title }}</h1> <p>{{ message }}</p> <form action="/" method="POST" enctype="multipart/form-data"> <div> <label for="ck1">Afgahanistan:</label> <input type="checkbox" id="ck1" name="checkbox" value="Afgahanistan"> </div> <div> <label for="ck2">Australia:</label> <input type="checkbox" id="ck2" name="checkbox" value="Australia"> </div> <div> <label for="ck3">England:</label> <input type="checkbox" id="ck3" name="checkbox" value="England"> </div> <div> <label for="ck4">France:</label> <input type="checkbox" id="ck4" name="checkbox" value="France"> </div> <div> <input type="submit" value="送信"> </div> </form> </body> </html> 3.index1.htmlのコード ```ここに言語を入力 <!doctype html> <html lang="ja"> <head> <meta charset="utf-8"> <meta name="viewport" content="width=device-width, initial-scale=1, shrink-to-fit=no"> <title>Hello World</title> </head> <body> <h1>{{ title }}</h1> {% block content %} {% for list1 in list1s %} <p>{{loop.index}}:{{list1}}</p> {% endfor %} {% endblock %} </form> </body> </html>コード

4.mysqlのtb3のテーブル内容

mysql> select * from tb3;
+--------------+------------+------------------+
| Country | Agency | email |
+--------------+------------+------------------+
| Afgahanistan | ABC Travel | 123@gmail.com |
| Australia | DEF Travel | 456@yahoo.com |
| England | GHI Travel | 789@hotmail.com |
| France | JFK Travel | 1111@yahoo.co.jp |
+--------------+------------+------------------+
4 rows in set (0.00 sec)

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

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

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

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

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

TakaiY

2021/05/01 07:51

そもそもこのコードは動かないのではありませんか? 質問の焦点になっているはずの「list1s」がどこにも定義されていません。 「(複数項目を選択した場合、最後にチェックした国(上記の例では、フランス)しか、HTML上で表示できません。)」となっているときのソースに差し替えてください。
yujin1202

2021/05/01 11:46

早速のコメントをありがとうございます。 大変失礼いたしました。 Pythonファイルの下から7行目で、list1sを定義していたのですが、"s"が抜けておりました。 従って、該当行を下記の様に修正しました。(このサイトに転記する際のミスでした。) また、修正後のコードで動作するのも、たった今、確認しました。 *** list1s = cursor.fetchall() #TakaiYさんのコメントを受け、誤字修正 *** HTML(index1.html)の方は、一切、変えておりません。 これで、如何でございましょうか? お手数をおかけしますが、教えて頂きたく。 よろしくお願いいたします。
guest

回答1

0

ベストアンサー

すくなくとも以下の場所はおかしいですね。

python

1 for name in names: 2 3 cursor = connection.cursor() 4 sql = "select Country, Agency, email from tb3 where Country=%s"; 5 cursor.execute(sql, (name,)) 6 7 list1s = cursor.fetchall() 8 print(list1) #コンソール上での動作確認用

※ ちなみに、最後のprintのインデントは直しています。すくなくとも元のコードはここでエラーになるはずです。

この処理は、namesにユーザが選択した国が入っていてそれをループで回していますが、list1sに追加するのでなく、その都度その結果を入れているだけなので、ループの最後の値がlist1sに設定された状態でループを抜けます。
なので、最後の国のデータしか表示されないのです。

ループの前でlist1sを空のリストとして定義してcursor.fetchall()の内容を追加していく必要があります。
追加するにあたっては、cursor.fetchall()の返り値によって、append()もしくはextend()のどちらかを使いましょう。

投稿2021/05/01 14:12

編集2021/05/01 14:15
TakaiY

総合スコア12747

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

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

yujin1202

2021/05/01 21:43 編集

TakaiYさん、ありがとうございまず。 (printのIndentの件、コピーした時にズレた様です。大変、失礼しました。) >list1sに追加するのでなく、その都度その結果を入れているだけなので、ループの最後の値が >list1sに設定された状態でループを抜けます。 このご説明は、大変、明瞭です。 なぜ、ダメなのか?は理解できました。 ただ、固定文字列とかをappendする方法はネットでいくらでもあったのですが、今回の様な可変する文字列をappendする方法が見つからず。。。 原因が分かったので、appendを使って書き直してみますが、何か参考のサイト記事か何かありましたら、教えて頂きたく。 引き続き、よろしくお願いいたします。
TakaiY

2021/05/02 10:39

固定文字列だろうと関数の返り値だろうとリストに追加する方法は同じです。 list1s.append(cursor.fetchall()) とすればいいし、たとえば、 list1 = cursor.fetchall() list1s.append(list1) のほうが理解しやすければそれでも。 重ねて書きますが、appendでなくextendにしなければうまく表示できないかもしれません。
yujin1202

2021/05/03 02:32

TakaiYさん、いつも教えてくださり、ありがとうございます。 すいません。 私の最初の回答が、ミスリーディングをしてしまったかも知れないのですが、最初のコードでもPythonのコンソール上では、選択した複数国はキチンと表示されております。 しかしながら、HTML上では、最後の一か国しか表示されないのが問題となっております。 従って、Pythonのコードではなく、HTMLの記載に問題があるのでは?と思っているのですが、 如何でしょうか?(TakaiYさんの御回答は、Pythonのコードの方の話だと思うのですが。。。。) 元のコードで言うと、具体的には、HTML(index1.html)の下記の部分に問題があると思っております。 御質問ばかりで申し訳ないのですが、引き続き、教えて頂きたく。 ========= <body> <h1>{{ title }}</h1> {% block content %} {% for list1 in list1s %} <p>{{list1}}</p> {% endfor %} {% endblock %} --!> </form> </body> ==========
TakaiY

2021/05/03 03:03

ミスリードしてないですよ。 HTMLには問題ないと思います。「list1s」にちゃんと複数国分の情報入っていれば、このHTML(jinja)の設定で一覧が表示されるはずです。 ただ、動かしたわけではないので、間違えている可能性はありますが、なにしろlist1sに1国分のデータしか入っていないはずなので、正しく書けていても1つしか表示されないはずです。 また、コンソールに全ての国の情報が表示されるのは、**for文の中**にprint分があって回る度に表示されているからです。 試しにfor文の中のprintを消して、**for文の外**(cursor.closeの後とか)にprint(list1s) をしてみると何が入っているかわかるはずです。
yujin1202

2021/05/03 04:35

TakaiYさん、 本当にありがとうございました! 解決しました。 すべての御指摘が、もっともであり、大変、勉強になりました。 これで実装に入れます。(GW中に解決できなかったら、どうしよう?と思っていたのですが、お陰様で解決です。) 改めて、ありがとうございました。 最終コードを、上記質問にも追記しておきますね。(Githubにも上げようと思います。) 勿論、ベストアンサーとさせて頂きます! 深謝です! 解決に役に立ったと言う意味では、特に下記コメントが有用でした。 ================ ① HTMLには問題ないと思います。 → こっちに問題があると思って、Python以上によく分かってないHTMLの本を凄い勢いで読み始めていたのですが、このコメントで切り分けが出来ました! ②ループの前でlist1sを空のリストとして定義してcursor.fetchall()の内容を追加していく必要があります。 → 自分で試行錯誤する時は、ループの中で空のリストを定義しておりました。確かに、for文の外でやらないとダメですね。深謝です! ③コンソールに全ての国の情報が表示されるのは、**for文の中**にprint分があって回る度に表示されているからです。 試しにfor文の中のprintを消して、**for文の外**(cursor.closeの後とか)にprint(list1s) をしてみると何が入っているかわかるはずです。 → なぜ、コンソール上ではできて、HTML上でダメなのか?がずっと分からなかったですが、printをforの「外」で書かないと切り分けができないですね。大変、有用でした! =====================
guest

あなたの回答

tips

太字

斜体

打ち消し線

見出し

引用テキストの挿入

コードの挿入

リンクの挿入

リストの挿入

番号リストの挿入

表の挿入

水平線の挿入

プレビュー

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

ただいまの回答率
85.48%

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

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

質問する

関連した質問