一行入力フォームに数字が入力されたら、SQLiteにてデータベースから検索し、該当する日本語名を表示させたいです。
入力フォームのアクション属性で飛んだCGIに最初のページと同じHTMLを書き、検索・情報取得後にデータを表示させたい場所へ文字を埋め込む、というやり方は知ることができました。
しかし、これですと、URLがCGIのものに変わってしまいます。
URLを遷移させることなく、一行入力フォームの内容をすぐに検索、結果を表示させる、ということは可能なのでしょうか?
-追記-
まずinput.pyで各種情報を入力しますが、この中の「活動場所」に数字を入れた際、それを「basyoID」として認識し、basyo.dbに入っているデータから「basyoNAME」を検索、それを直ちに表示させたいのです。
input.pyがこちらです。
python
1#!/usr/local/bin/python3 2# -*- coding: utf-8 -*- 3 4import sys 5import io 6import sqlite3 7import cgi 8import cgitb 9cgitb.enable() 10# 文字化け回避 11sys.stdout = io.TextIOWrapper(sys.stdout.buffer, encoding='utf-8') 12 13# HTMLここから 14#print("Content-type: text/html; charset=utf-8") 15print('Content-Type: text/html; charset=UTF-8\n') 16print( 17""" 18<html lang="ja"> 19<head> 20 <meta charset="utf-8"> 21<TITLE></TITLE> 22</HEAD> 23<BODY> 24 25<FORM name="form" method="post" action="basyo_kensaku.py"> 26<P>避難場所</P> 27<P>活動場所ID</P> 28<INPUT size="8" type="text" maxlength="8" required name="basyoID"> 29<P>上の入力フォームにIDを入力したら、この場所にbasyo.dbから検索した場所を表示させたいです。</P> 30<BR> 31</BODY> 32</HTML> 33""" 34) 35 36# データベース接続 37conn = sqlite3.connect('basyo.db') 38c = conn.cursor() 39# テーブル作成 40c.execute('CREATE TABLE IF NOT EXISTS basyo(basyoID integer, basyoNAME text);') 41
続いて、場所を検索させるbasyo_kensaku.pyがこちらです。
python
1#!/usr/local/bin/python3 2# -*- coding: utf-8 -*- 3 4import sys 5import io 6import sqlite3 7import cgi 8import cgitb 9cgitb.enable() 10 11# 文字化け回避 12sys.stdout = io.TextIOWrapper(sys.stdout.buffer, encoding='utf-8') 13 14# データベースに接続する 15conn = sqlite3.connect('basyo.db') 16c = conn.cursor() 17 18#formにセットされた値を取得 19form = cgi.FieldStorage() 20basyoID = form.getfirst('basyoID','') 21#basyoIDでbasyo.dbを検索 22sql = ('SELECT basyoNAME from basyo where basyoID=' + basyoID) 23c.execute(sql) 24basyoNAME = c.fetchone
以上、何卒ご教授下さいませ。
Pythonは直接関係ないのでは。サーバー側がPythonのCGIと言うことでしょうか。
> URLを遷移させることなく、一行入力フォームの内容をすぐに検索、結果を表示させる、ということは可能なのでしょうか?
HTML, JavaScript, Ajax, jQueryあたりに関わる話題だと思います。
フォームの見た目だけの話でいえば回答として「可能」で終わってしまう質問内容ですね。
ご教授誠に有難うございます。HTML側で対応するものでしたか。
ここまでに作成したコードも掲載致しましたのでご確認下さい。
Javascriptで入力フォームの変更を監視して、Ajax でサーバーにリクエスト投げてデータ持ってくるようにすればページ遷移しなくても内容は変更できます。
サーバー側もCGI自前で作るより flask などのフレームワーク使ったほうが楽だと思います。
https://qiita.com/strawberryjam/items/710a21329db109f62084
ご教授誠に有難うございます。やがてはレンタルサーバーへ置く予定のCGIなのですが、レンタルサーバーがフレームワークに対応しているかが心配です。
レンタルサーバーで Python が動くのであれば、Python のフレームワークも動かせると思います。フレームワークはレンタルサーバーが用意してくれるものではなく、自分で導入するものです。
非常に参考になりました。有難うございました。
formのaction属性を削り、postされたformdata中のbasyoIDの有無を確認することで、初期表示なのか検索なのかを判断できると思います。
検索なら、SELECTクエリを発行し、結果をprintすることで1つのURLにすることが可能です。
なお、レンタルサーバーで公開を考えているとのことなので、2点ほどセキュリティ関連の指摘をさせて頂きます。
①DBの結果をprintするときはhtml.escape()を使ってエスケープしないと、HTMLタグなどが入った場合に正しく動作しません。
②
sql = ('SELECT basyoNAME from basyo where basyoID=' + basyoID)
c.execute(sql)
は
sql = ('SELECT basyoNAME from basyo where basyoID=?')
c.execute(sql, [basyoID])
としないとbasyoIDにSQLの構文を埋め込まれたときに危険です。
flaskなどフレームワークを使うと多少便利ですが、Fastとかが付かないCGIだとただでさえ遅いpythonがもっと遅くなるので、用途によってはあまりオススメしません。djangoとかになると、CGIだと普通は動きませんしね。
今回はフォームデータを使った同一URL遷移による全画面書き換えの方法で考えましたが、APIを使ってデータを取得することで画面遷移させず、1部分だけ書き換えるSPAという方式(やその派生形もいろいろ)があります。ReactやVueなどいまどきのフロントはそちらの方式を良く使うので、余裕があったらそういう方法も見てみてください。
dameo様、ご意見誠に有難うございます。
-*-*-*-*
『formのaction属性を削り、postされたformdata中のbasyoIDの有無を確認することで、初期表示なのか検索なのかを判断できると思います。
検索なら、SELECTクエリを発行し、結果をprintすることで1つのURLにすることが可能です。
-*-*-*-*
この部分が理解できませんでした。POSTするということは現ページからどこかへ送信するということで、どうしても他のページへ移動してしまうのではないでしょうか?
-*-*-*-*-*
①DBの結果をprintするときはhtml.escape()を使ってエスケープしないと、HTMLタグなどが入った場合に正しく動作しません。
②
sql = ('SELECT basyoNAME from basyo where basyoID=' + basyoID)
c.execute(sql)は
sql = ('SELECT basyoNAME from basyo where basyoID=?')
c.execute(sql, [basyoID])
としないとbasyoIDにSQLの構文を埋め込まれたときに危険です。
-*-*-*-*-*-*
この部分は理解できましたので直ちに修正を行いました。有難うございました。
> -*-*-*-*
> 『formのaction属性を削り、postされたformdata中のbasyoIDの有無を確認することで、初期表示なのか検索なのかを判断できると思います。
> 検索なら、SELECTクエリを発行し、結果をprintすることで1つのURLにすることが可能です。
> -*-*-*-*
> この部分が理解できませんでした。POSTするということは現ページからどこかへ送信するということで、どうしても他のページへ移動してしまうのではないでしょうか?
サーバーに送信(submit)し、画面遷移は起こりますが、URLは変わりませんよ
初回は例えば
GET /cgi-bin/input2.py HTTP/1.1
...
だったリクエストがフォーム入力してEnterしたときは
POST /cgi-bin/input2.py HTTP/1.1
...
となります。新しい画面がレスポンスとして返り、そのHTMLで全画面書き換えられますが、アドレスバー上のURLは変わらないということです。
あなたの回答
tips
プレビュー