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

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

ただいまの
回答率

87.78%

(PYTHON)URLを変えることなく一行入力フォームのデータをDBから検索させたい

受付中

回答 0

投稿 編集

  • 評価
  • クリップ 0
  • VIEW 284

score 13

一行入力フォームに数字が入力されたら、SQLiteにてデータベースから検索し、該当する日本語名を表示させたいです。

入力フォームのアクション属性で飛んだCGIに最初のページと同じHTMLを書き、検索・情報取得後にデータを表示させたい場所へ文字を埋め込む、というやり方は知ることができました。

しかし、これですと、URLがCGIのものに変わってしまいます。
URLを遷移させることなく、一行入力フォームの内容をすぐに検索、結果を表示させる、ということは可能なのでしょうか?

-追記-

まずinput.pyで各種情報を入力しますが、この中の「活動場所」に数字を入れた際、それを「basyoID」として認識し、basyo.dbに入っているデータから「basyoNAME」を検索、それを直ちに表示させたいのです。

input.pyがこちらです。

#!/usr/local/bin/python3
# -*- coding: utf-8 -*-

import sys
import io
import sqlite3
import cgi
import cgitb
cgitb.enable()
# 文字化け回避
sys.stdout = io.TextIOWrapper(sys.stdout.buffer, encoding='utf-8')

# HTMLここから
#print("Content-type: text/html; charset=utf-8")
print('Content-Type: text/html; charset=UTF-8\n')
print(
"""
<html lang="ja">
<head>
  <meta charset="utf-8">
<TITLE></TITLE>
</HEAD>
<BODY>

<FORM name="form" method="post" action="basyo_kensaku.py">
<P>避難場所</P>
<P>活動場所ID</P>
<INPUT size="8" type="text" maxlength="8" required name="basyoID">
<P>上の入力フォームにIDを入力したら、この場所にbasyo.dbから検索した場所を表示させたいです。</P>
<BR>
</BODY>
</HTML>
"""
)

# データベース接続
conn = sqlite3.connect('basyo.db')
c = conn.cursor()
# テーブル作成
c.execute('CREATE TABLE IF NOT EXISTS basyo(basyoID integer, basyoNAME text);')


続いて、場所を検索させるbasyo_kensaku.pyがこちらです。

#!/usr/local/bin/python3
# -*- coding: utf-8 -*-

import sys
import io
import sqlite3
import cgi
import cgitb
cgitb.enable()

# 文字化け回避
sys.stdout = io.TextIOWrapper(sys.stdout.buffer, encoding='utf-8')

# データベースに接続する
conn = sqlite3.connect('basyo.db')
c = conn.cursor()

#formにセットされた値を取得
form = cgi.FieldStorage()
basyoID = form.getfirst('basyoID','')
#basyoIDでbasyo.dbを検索
sql = ('SELECT basyoNAME from basyo where basyoID=' + basyoID)
c.execute(sql)
basyoNAME = c.fetchone

以上、何卒ご教授下さいませ。

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

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

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

    クリップを取り消します

  • 良い質問の評価を上げる

    以下のような質問は評価を上げましょう

    • 質問内容が明確
    • 自分も答えを知りたい
    • 質問者以外のユーザにも役立つ

    評価が高い質問は、TOPページの「注目」タブのフィードに表示されやすくなります。

    質問の評価を上げたことを取り消します

  • 評価を下げられる数の上限に達しました

    評価を下げることができません

    • 1日5回まで評価を下げられます
    • 1日に1ユーザに対して2回まで評価を下げられます

    質問の評価を下げる

    teratailでは下記のような質問を「具体的に困っていることがない質問」、「サイトポリシーに違反する質問」と定義し、推奨していません。

    • プログラミングに関係のない質問
    • やってほしいことだけを記載した丸投げの質問
    • 問題・課題が含まれていない質問
    • 意図的に内容が抹消された質問
    • 過去に投稿した質問と同じ内容の質問
    • 広告と受け取られるような投稿

    評価が下がると、TOPページの「アクティブ」「注目」タブのフィードに表示されにくくなります。

    質問の評価を下げたことを取り消します

    この機能は開放されていません

    評価を下げる条件を満たしてません

    評価を下げる理由を選択してください

    詳細な説明はこちら

    上記に当てはまらず、質問内容が明確になっていない質問には「情報の追加・修正依頼」機能からコメントをしてください。

    質問の評価を下げる機能の利用条件

    この機能を利用するためには、以下の事項を行う必要があります。

質問への追記・修正の依頼

  • dameo

    2021/01/19 21:51

    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などいまどきのフロントはそちらの方式を良く使うので、余裕があったらそういう方法も見てみてください。

    キャンセル

  • jyansinkai

    2021/01/20 14:35

    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の構文を埋め込まれたときに危険です。
    -*-*-*-*-*-*
    この部分は理解できましたので直ちに修正を行いました。有難うございました。

    キャンセル

  • dameo

    2021/01/20 21:53

    > -*-*-*-*
    > 『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は変わらないということです。

    キャンセル

まだ回答がついていません

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

  • ただいまの回答率 87.78%
  • 質問をまとめることで、思考を整理して素早く解決
  • テンプレート機能で、簡単に質問をまとめられる

関連した質問

同じタグがついた質問を見る