iT邦幫忙

0

在Flask框架中,在html做下拉式選單,選完顯示連結MySQL資料庫的資料

  • 分享至 

  • xImage

各位IT邦大大們好

小弟目前在已經在Flask框架中,寫好Python連結MySQL資料庫如下:

app = Flask(name)
app.config['SQLALCHEMY_DATABASE_URI'] = "mysql://test:test@127.0.0.1:3306/test"
db = SQLAlchemy(app)

class Person(db.Model):
tablename = 'person'
id = db.Column('id', Integer, primary_key=True)
name = db.Column('name', String(255))
age = db.Column('age', Integer)

也宣告好一個function:
def list_persons():
persons = Person.query.all()

連結的語法如下:
@app.route('/')
def index():
return render_template('index.html', persons=persons)

現在裡面的測試資料庫裡的資料有:
id name age
01 Justin 24
02 Mary 18

那如果我想要在index.html網頁中做下拉式選單
讓使用者下拉式選擇欄位id,然後按按鈕做確認
結果畫面跑出MySQL資料庫裡欄位name及age的資料
那我在html要怎麼下語法,懇請IT邦大大們解法,謝謝。

圖片
  直播研討會
圖片
{{ item.channelVendor }} {{ item.webinarstarted }} |
{{ formatDate(item.duration) }}
直播中

2 個回答

2
froce
iT邦大師 1 級 ‧ 2018-05-25 08:16:19
最佳解答

1.利用form送出ID,後端接收到ID後,再帶出個人資料,重新渲染。
2.或是利用ajax送出ID,去得到個人資料,然後利用JS動態新增出DOM。

因為我個人是用DJANGO,flask沒那麼熟。有空的話我之後會補上範例。

另外看了你的code,其中:

def list_persons():
    persons = Person.query.all()
    
@app.route('/')
def index():
    return render_template('index.html', persons=persons)

這樣子不會回傳persons到你的index.html喔,因為你只定義出list_persons()這個函式,但沒執行過。

改成:

def list_persons():
    return Person.query.all()
    
@app.route('/')
def index():
    persons = list_persons()
    return render_template('index.html', persons=persons)

或者乾脆list_persons()不要:

@app.route('/')
def index():
    persons = Person.query.all()
    return render_template('index.html', persons=persons)
看更多先前的回應...收起先前的回應...
froce iT邦大師 1 級 ‧ 2018-05-25 10:27:51 檢舉

給你基本的form作法就好,等你瞭解了以後,需要ajax很快就上手了。
範例:

from flask import Flask, render_template, request
from flask_sqlalchemy import SQLAlchemy

app = Flask(__name__)
app.config['SQLALCHEMY_DATABASE_URI'] = 'sqlite:////test.db'
db = SQLAlchemy(app)


# 注意你model寫錯了。
class Person(db.Model):
    tablename = 'person'
    id = db.Column(db.Integer, primary_key=True)
    name = db.Column(db.String(255))
    age = db.Column(db.Integer)


@app.route('/',  methods=['GET', 'POST'])
def hello_world():
    persons = Person.query.all()  # 先取得所有人
    
    # 如果form裡面有pid值
    if 'pid' in request.form:
        pid = request.form.get('pid', 0, type=int)
        the_one = Person.query.get(pid)
        
        # 多傳回一個你取到的人(the_one)
        return render_template("index.html", persons=persons, the_one=the_one)

    # 傳回所有的人
    return render_template("index.html", persons=persons)


if __name__ == '__main__':
    app.run()

index.html:

<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <meta http-equiv="X-UA-Compatible" content="ie=edge">
    <title>Document</title>
</head>
<body>

<!-- 建立一個form傳出,使用POST -->
<form method="POST">
    <!-- 列出所有id -->
    <select name="pid" id="pid">
        {% for p in persons %}
        <option>{{ p.id }}</option>
        {% endfor %}
    </select>
    <input type="submit" value="送出">
</form>

<!-- 假設有傳出the_one,顯示個人資料 -->
{% if the_one %}
    <div>姓名:{{the_one.name}}</div>
    <div>年齡:{{the_one.age}}</div>
{% endif %}
</body>
</html>

資料庫我懶得用mysql,用sqlite3做示範。

froce iT邦大師 1 級 ‧ 2018-05-25 10:32:26 檢舉

flask-WTF應該是作form資料驗證的功能,不是必要的。
然後這麼簡單的東西我竟然寫了一個小時...Orz
工具果然還是用習慣的好用。

toru0516 iT邦新手 5 級 ‧ 2018-05-25 13:08:39 檢舉

感謝 froce 大的解答,我再試試看。原本也是在用Django,不過後來卻要改用Flask,變成整個框架架構要從零開始學起,不過幸好都是在Python下進行開發XD

froce iT邦大師 1 級 ‧ 2018-05-25 13:13:05 檢舉

有Django基礎這應該不難做啊?
基本上的東西都一樣,只有request、SQLAlchemy要查一下而已。

froce iT邦大師 1 級 ‧ 2018-05-26 10:24:27 檢舉

順便寫了ajax版的,主要是javascript的操作。
code要寫的稍微多一點,不過這樣可以分離html,而且更靈活。
index.py

from flask import Flask, render_template, request
from flask_sqlalchemy import SQLAlchemy
import os

app = Flask(__name__)
# 將db放在專案的資料夾
db_path = os.path.join(os.path.dirname(os.path.abspath(__file__)), "test.db")
app.config['SQLALCHEMY_DATABASE_URI'] = 'sqlite:////{}'.format(db_path)
db = SQLAlchemy(app)


class Person(db.Model):
    tablename = 'person'
    id = db.Column(db.Integer, primary_key=True)
    name = db.Column(db.String(255))
    age = db.Column(db.Integer)


# index.html目前僅列出所有人之id
@app.route('/')
def all_persons():
    persons = Person.query.all()  # 先取得所有人
    # 傳回所有的人
    return render_template("index.html", persons=persons)


# ajax取得人員資訊
@app.route('/GET/Person/<int:pid>')
def ajax_get_person_info(pid):
    the_one = Person.query.get(pid)
    if the_one:
        # 另開模版(person_info.html)給ajax去做回應
        return render_template('person_info.html', the_one=the_one)
    else:
        # 找不到人的回傳
        return "<div>Sorry,查無此人喔!!<div>"

if __name__ == '__main__':
    # 初始化db
    if not os.path.exists(db_path):
        db.create_all()
        db.session.add(Person(name="Jack", age=24))
        db.session.add(Person(name="Mary", age=18))
        db.session.commit()

    app.run()

index.html,現在可以看到DOM結構是只有列出ID而已了。

<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <meta http-equiv="X-UA-Compatible" content="ie=edge">
    <title>Document</title>
    <script src="https://code.jquery.com/jquery-3.3.1.min.js" integrity="sha256-FgpCb/KJQlLNfOu91ta32o/NMZxltwRo8QtmkMRdAu8="
        crossorigin="anonymous"></script>
</head>
<body>
    <!-- 不使用form了,所以submit也取消 -->
    <select name="pid" id="pid">
        {% for p in persons %}
        <option>{{ p.id }}</option>
        {% endfor %}
    </select>
    <input type="button" value="送出" id="btn">

    <!-- 顯示人員資訊用 -->
    <div id="display">

    </div>
</body>
</html>

<script>
    // ajax
    $('#btn').click(function(){
        var id = $('#pid').val();
        $.get({
            url: "/GET/Person/" + id,
        }).done(function(res){
            $('#display').empty();
            $('#display').append(res);
        })
    });
</script>

person_info.html

<div>姓名:{{ the_one.name }}</div>
<div>年齡:{{ the_one.age }}</div>
toru0516 iT邦新手 5 級 ‧ 2018-05-31 20:46:00 檢舉

感謝froce 大提供的code,修改一下我所需要個格式後,可以執行,ajax版本我會在學習學習,剛接觸這塊,很多地方還不是很懂。
/images/emoticon/emoticon32.gif

toru0516 iT邦新手 5 級 ‧ 2018-05-31 21:19:04 檢舉

我想再請教 froce 大,那如果是要做兩個連動的下拉式選單,小弟我最近拿到一份資料庫如下:

ID Model_Name value_without time
0050 Multiple Regression 0.5781 13.03
0050 Logistic Regression 0.587 10.93
0051 Multiple Regression 0.5158 10.98
0051 Logistic Regression 0.572 10.16
0052 Multiple Regression 0.5734 14.67
0052 Logistic Regression 0.5396 12.42

也就是先選擇ID下拉式選單,然後才可以再選擇Model_Name下拉式選單
,最後才從資料庫撈出 value_without 和 time,那是否可以直接在index.html直接再新增即可?

froce iT邦大師 1 級 ‧ 2018-05-31 21:57:30 檢舉

1.你可以用2個form去做,然後利用隱藏的input去辨識目前做到哪。

<form>
    <input type="hidden" name="step1" />
</form>

<form>
    <input type="hidden" name="step2" />
</form>

在flask可以這樣檢查:

if step1 in request.form:
    ...

if step2 in request.form:
    ...

2.不過我不會這樣做,我會先對ID和Model_Name做DISTINCT,得到這兩個欄位的set(不重複集合),然後一次送出給form,使用者直接選完ID和Model_Name再傳回數值。
這樣只要一次submit就行。

toru0516 iT邦新手 5 級 ‧ 2018-05-31 22:59:24 檢舉

敢問第二個的語法要怎麼下,謝謝 froce 大
/images/emoticon/emoticon33.gif

froce iT邦大師 1 級 ‧ 2018-05-31 23:15:41 檢舉

model_Name = db.session.query(ExamData.model_Name).distinct()

不過關鍵字都給你了,麻煩自己練習google一下。

0
paicheng0111
iT邦大師 5 級 ‧ 2018-05-24 22:15:06

我只會把資料全部拉出來,寫法大概如下:

<table>
<tr>
<th>id</th>
<th>name</th>
<th>age</th>
</tr>
{% for person in persons %}
<tr>
<td>{{ peron[0] }}</td>
<td>{{ peron[1] }}</td>
<td>{{ peron[2] }}</td>
</tr>
{% endfor %}
</table>

要寫出你的需求,首先要你的index.html中要有form,還要讓controller可以吃到form的值query出你想要的人。
這些可能需要安裝flask-WTF。

建議你可以去https://blog.miguelgrinberg.com/post/the-flask-mega-tutorial-part-i-hello-world 一步一步看。

toru0516 iT邦新手 5 級 ‧ 2018-05-25 13:10:04 檢舉

感謝 pcw 大的回答,有時間我再去鑽研flask-WTF套件。

我要發表回答

立即登入回答