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

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

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

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

MySQL

MySQL(マイエスキューエル)は、TCX DataKonsultAB社などが開発するRDBMS(リレーショナルデータベースの管理システム)です。世界で最も人気の高いシステムで、オープンソースで開発されています。MySQLデータベースサーバは、高速性と信頼性があり、Linux、UNIX、Windowsなどの複数のプラットフォームで動作することができます。

Python

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

Q&A

解決済

2回答

5964閲覧

【python+mysql】select文のwhere句に、動的に変化する単語を挿入する書き方を教えてください。

yujin1202

総合スコア56

Flask

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

MySQL

MySQL(マイエスキューエル)は、TCX DataKonsultAB社などが開発するRDBMS(リレーショナルデータベースの管理システム)です。世界で最も人気の高いシステムで、オープンソースで開発されています。MySQLデータベースサーバは、高速性と信頼性があり、Linux、UNIX、Windowsなどの複数のプラットフォームで動作することができます。

Python

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

0グッド

0クリップ

投稿2021/04/25 14:17

編集2021/04/26 08:33

丸一日、試行錯誤していたのですが、どうしても上手く行かないので、教えてください。

1.<やりたい事>
pythonで、Mysql DBからデータを取得し、それをHTMLに表示しようとしております。
DBは、下記の様になっております。
イメージ説明

HTML上で、下記様にチェックを入れて、送信ボタンを押すと、
イメージ説明

この様に表示したいと思っております。
イメージ説明

2.<質問>
Pythonコードは項番3に記載しておきますが、下記1)の様に、チェックされた項目(国名)は、namesと言う変数で取得しております。

1)names = request.form.getlist('checkbox')

2)ここで、print(names) とすると、想定通り、チェックされたのを返します。
(想定通りです。)
>['Afgahanistan', 'Australia', 'France']

3)for name in names: 
<tab> print(name) 
また、この様にすると、国名を個別に返してきます。(これも想定通りです。)

Afgahanistan
Australia
France

4)国名(この場合は、上記3か国)をSelect文のwhere句に代入して、変数として、情報を取りたいと考え、下記(a)の様にSelect文を書いたのですが、これが動作しません。
(a) sql = "select Country, Agency, email from tb3 where Country='name'";
(このsql文をPythonに書くと、エラーは出ないのですが、出力が真っ白な画面となります。)

尚、問題の切り分けの為に、このsql文のWhere句を下記の様(b)に個別国名(この例では、Afgahanistan)に書き換えると、Afgahanistanのデータを正常に返してきます。ついては、やはり、上記(a)の'name'の部分がオカシイのでは?と思っております。
(b) sql = "select Country, Agency, email from tb3 where Country='Afgahanistan'";

繰り返しになるのですが、多分、(a)の「where Country='name';」のnameの部分で、変数がキチンと取得できていないと思うのですが、如何でしょうか?

3.下記にPythonコードを記載します。
また、本件とは関係ないと思いますが、一応、HTMLのコードも記載しておきます。
よろしくお願いいたします。

<Pythonのコード>

from flask import Flask, render_template,request import pymysql app = Flask(__name__) @app.route('/', methods=['GET']) def get(): return render_template('index1.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') print(names) for name in names: print(name) <tab> sql = "select Country, Agency, email from tb3 where Country='name'"; <tab> cursor = connection.cursor() <tab> cursor.execute(sql) <tab> listx1s = cursor.fetchall() <tab> cursor.close() <tab> connection.close() <tab> return render_template( 'index2.html', listx1s = listx1s) if __name__ == '__main__': app.run() コード

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

<Index2.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> {% block content %} {% for listx1 in listx1s %} <p>{{listx1}}</p> {% endfor %} {% endblock %} </form> </body> </html>

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

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

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

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

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

guest

回答2

0

SQLのWHERE IN句およびパラメータ引数を用いたコード例です。
DB関連の最小限のコードサンプルとなっています。
なお、プレースホルダの文字はDB(ドライバ)依存なのですがmysqlでは?ではなく%sのようですので適宜修正ください。
参考:mysqlclientのプレースホルダでIN句を使う

Python

1 2import sqlite3 3 4con = sqlite3.connect('test.db') 5cursor = con.cursor() 6 7for names in [[],['Japan'],['Japan','England']]: 8 9 if not names: 10 continue 11 12 holder = ','.join(['?' for _ in names]) # mysqlは'%s'かも 13 sql = f'select Country from tb3 where Country in ({holder})' 14 print(sql) 15 cursor.execute( sql, names) 16 for line in cursor.fetchall(): 17 print(line) 18 19cursor.close() 20con.close() 21 22#select Country from tb3 where Country in (?) 23#('Japan',) 24#select Country from tb3 where Country in (?,?) 25#('England',) 26#('Japan',)

投稿2021/04/26 09:31

can110

総合スコア38234

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

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

hayataka2049

2021/04/26 11:59 編集

これ思いつきませんでした……その手があったか……
can110

2021/04/26 12:23

ちょっと泥臭いですが… プレースホルダ部分を可変で指定する方法を検索しても意外とひっかかってこなくて スマートな方法がないんですよね。
yujin1202

2021/04/27 15:16

詳しい御説明を、ありがとうございました。 御回答を頂いてから、丸一日以上、色々と試行錯誤したのですが、上手くいきません。 私自身がプレースホルダ―をきちんと理解できていないのが原因です。 もう少し、調べてみます。取り急ぎ、お礼まで。。。
yujin1202

2021/04/28 08:16

頂いた御回答とリンク記事を熟読し、内容は私なりに理解致しました。 大変、勉強になりました。 ありがとうございました。 ただ、実装に適用しようとすると、どうしても上手くいきません。(これだけ情報を頂ければ、解決できるだろうと思って、「解決済」には、してしまったのですが。。。) とは言いつつも、分からない部分を、大幅に狭める事は出来たので、この質問は一旦、クローズと致します。問題を切り分けた上で、別の質問(もっと端的な質問)を立てますので、もし可能で御座いましたら、そちらにもコメントを頂きたく。 重ねて、ありがとうございました。
guest

0

ベストアンサー

プレースホルダという機能を使います。

python

1 sql = "select Country, Agency, email from tb3 where Country=%s"; 2 cursor.execute(sql, (name, ))

これで意図通り動くのかどうかはわかりません(ループの最後に見たnameでしか取れないはず)。そちらはご自身でどうにか直してください。

投稿2021/04/25 14:44

hayataka2049

総合スコア30933

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

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

yujin1202

2021/04/25 15:26

早速、ありがとうございます。 頂いたコードですが、確かに御指摘の通り、「ループの最後に見たnameでしか取れない」です。 ここは何とか工夫してみます。 また、プレースホルダ―と言う機能を調べてみます。取り急ぎ、お礼申しあげます。
yujin1202

2021/04/26 02:57

昨夜から、色々と調べたのですが、「ループの最後に見たnameでしか取れない」と言う問題が解決できません。何か、参考になるサイト等を御存じの方がいらっしゃいましたら、教えて頂きたく。 よろしくお願いいたします。
FiroProchainezo

2021/04/26 04:36

たぶん以下が参考になると思います。 https://www.ipentec.com/document/sql-in-operator FlaskでSQL操作をする場合は、Flask-SQLAlchemyを利用すると簡単です。 Flask-SQLAlchemyはSQLAlchemyとは別物ですので情報を検索するときは気をつけてください。
hayataka2049

2021/04/26 07:53

スマートさは若干犠牲になりますが、forループの中に入れて複数回executeを叩けば良いのでは。
yujin1202

2021/04/26 09:03

ありがとうございます。 色々と御意見を頂いたり、試行錯誤する中で、「何が分からないのか?」が分かってきました。 SQL文の一般的な事だと思いますが、一つ教えてください。 <ご説明> 1. pymysqlでSQL文を書く際に、 (a) sql="select Country, Agency, email from tb3 where Country ='England'"; と書けば、勿論、正しい値を返します。 2. しかしながら、 print(" ' "+names[1]+" ' ") >'England' と返してくる状態で、(b)の様に書くと、(a)と同じ様に動作しません。 (b) sql="select Country, Agency, email from tb3 where Country =" ' "+names[1]+" ' ""; (因みに、ここでprint(sql)を実行すると、「" ' "+names[1]+" ' "」が、’England’に変換されないで、そのまま表示されます。) <御質問> (b)のwhere句に、names[1]をセットするには、どういう書き方になるのでしょうか? 基本的な事で恐縮です。 ただ、ここをクリアすれば、後は、解決できると思っております。 よろしくお願いいたします。
hayataka2049

2021/04/26 11:55

プレースホルダを使うのであれば、 sql = "select Country, Agency, email from tb3 where Country=%s" cursor.execute(sql, (names[1], )) という感じでやります。 「文字列でSQLを組み立てるのはSQLインジェクションあるから駄目」という話はちょっとググれば無限に出てきますが、敢えてやるなら "select Country, Agency, email from tb3 where Country ='" + names[1] + "'" でしょうか。
yujin1202

2021/04/26 12:20

ありがとうございます。 お陰様で、やっと大枠を理解しました。 確かに、私のやろうとしている事は、「SQLインジェクション」ですね。(言われてみて、初めて気が付きました。)  従って、SQLインジェクションの「記法」については、情報があまりネットになく、出てくるのは、プレースホルダ―の話と言う事になるのですね。 誠に有難うございました。私の頭の中で、話が繋がりました。 ベストアンサーとさせて頂きます。
guest

あなたの回答

tips

太字

斜体

打ち消し線

見出し

引用テキストの挿入

コードの挿入

リンクの挿入

リストの挿入

番号リストの挿入

表の挿入

水平線の挿入

プレビュー

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

ただいまの回答率
85.50%

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

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

質問する

関連した質問