2021年8月17日 星期二

使用 Flask Login 模組

學習目標:
  • 利用 Flask Login 模組,控制站台運作!

使用 Flask Login 模組
  1. 新增 app/templates/login.html 檔案:
    {% extends "base.html" %}
    {% block title %}大學麵店系統管理區{% endblock %}


    {% block main %}
    <div class="container">
    <div class="row">
    <div class="col">
    <h1>後台管理</h1>
    <form action="/logins" method="post">
    <label for="loginname">登入帳號</label>
    <input type="text" id="loginname" placeholder="請輸入帳號" name="loginname">
    <br>
    <br>
    <label for="passwrod">登入密碼</label>
    <input type="password" id="password" placeholder="請輸入密碼" name="password">
    <br>
    <input type="submit" value="送出">
    </form>
    </div>
    </div> {% endblock %}
  2. 修改 requirements.txt
    (前面略過....)
    Flask-Login>=0.4.1
    
  3. 修改 app/__init__.py
    (前面略過....)
    from flask_login import LoginManager
    (中間略過....)
    # 導入加密 key
    app.secret_key = config.get('Flask','SecretKey')
    
    lm = LoginManager()
    lm.init_app(app)
    lm.session_protection = "strong"
    lm.login_view = 'login'
    lm.login_message = '請輸入帳號密碼'
    
    # 導入其他的程式模組
    from app import router, linebotmodules, loginmodels
    
  4. 使用 terminal 介面,產生 secret_key 內容:
    C:\workspace\LineBot> python
    >>> import os
    >>> os.urandom(16).hex()
    (產生一堆編碼)
    
  5. 修改 config.ini 檔案內容:
    [Flask]
    SecretKey = 上個步驟產生的一堆編碼
    
  6. 新增 app/loginmodels.py 檔案內容:
    from flask_login import UserMixin
    from app import lm
    
    class User(UserMixin):
        pass
    
    @lm.user_loader
    def user_loader(users):
        if users not in users_dict:
            return
    
        user = User()
        user.id = users
        return user
    
    @lm.request_loader
    def request_loader(request):
        user = request.form.get('user_id')
        if user not in users_dict:
            return
        
        user = User()
        user.id = user
    
        user.is_authenticated = request.form['password'] == users_dict[user]['password']
    
        return user
    
    users_dict = {'Owner': {'password': 'HelloWorld'}}
    
  7. 修改路由檔案 app/router.py
    (前面略過....)
    from flask import request, render_template, url_for, redirect, flash
    from flask_login import login_user, logout_user, login_required, current_user
    from app.loginmodels import User, users_dict
    
    @app.route('/logins', methods=['GET','POST'])
    def login():
        if request.method == 'GET':
            return render_template("login.html")
    
        user = request.form['loginname']
        conditionA = user in users_dict
        conditionB = request.form['password'] == users_dict[user]['password']
    
        if conditionA and conditionB:
            user1 = User()
            user1.id = user
            login_user(user1)
            flash(f'{user}!Welcome home!')
            return redirect(url_for('home'))
    
        flash('login failed...')
        return render_template('login.html')
    
    @app.route('/logout')
    def logout():
        user = current_user.get_id()
        logout_user()
        flash(f'{user}!logout!')
        return render_template('login.html')
    
    @app.route('/show_records')
    @login_required
    def show_records():
        python_records =web_select_overall()
        return render_template('show_records.html', html_records=python_records)
    (後面略過....)
    
  8. 修改 app/templates/base.html
    {% if current_user.is_authenticated %}
    <li class="nav-item">
    <a class="nav-link" href="http://mylinebothellotux.herokuapp.com/showmenu">麵店菜單</a>
    </li>
    <li class="nav-item">
    <a class="nav-link" href="http://mylinebothellotux.herokuapp.com/showads">活動訊息</a>
    </li>
    <li class="nav-item">
    <a class="nav-link" href="http://mylinebothellotux.herokuapp.com/logout">登出</a>
    </li>
    {% else %}
    <li class="nav-item">
    <a class="nav-link" href="http://mylinebothellotux.herokuapp.com/logins">登入</a>
    </li>
    {% endif %}
  9. 將專案送上 Heroku 主機!

2021年8月15日 星期日

使用 Line Bot 圖文選單

學習目標:
  • 利用 Line Bot 圖文選單,進行互動!

使用 Line Developer 工具建立圖文選單
  1. 登入 Line Developer,選用 Line Official Account Manager :
  2. 在主頁選項,選擇「聊天室相關」的圖文選單:
  3. 閱讀注意事項:
  4. 建立圖文選單:
  5. 輸入需要的項目內容:
  6. 在內容設定中,選擇版型:
  7. 選擇需要的版型,按下「確定」!
  8. 按下「建立圖片」:
  9. 為每個對達框選擇圖片檔案:
    PS: 可按「Ctrl」+ 三個圖片框,同時上傳三個圖檔,進行設定!
  10. 指定「A」區塊類型為:文字,並輸入文字內容:
  11. 完成後,可以按下「儲存」,完成編輯!
  12. 打開 line 聊天室,可看到該圖文框!

試寫自己的訂購單
  1. 在 app/router.py 中,加入下列內容:
    @app.route('/orderMenu/<nodes>')
    def orders(nodes):
    return render_template("orderMenu.html",nodeslist=nodes)

    @app.route('/orderMenu',methods = ['GET','POST'])
    def addorders():
    if request.method == 'POST':
    print(request.form)
    data = ""
    for key,value in request.form.items():
    data += value
    data += ','
    data = data[:-1]
    connectDB.addOrders(data)
    return render_template("showOrders.html")
    else:
    return render_template("showOrders.html")

    # 顯示訂單列表
    @app.route("/showOrders")
    def showOrders():
    orderslists = connectDB.showOrders()
    return render_template('showOrders.html',menulist=orderslists)
  2. 在 app/templates/orderMenu.html
    {% extends "base.html" %}
    {% block title %}My Web Site{% endblock %}
    {% block main %}
    <div class="container my-5 py-5">
    <div class="row">
    <div class="rol">
    <h1>{{ nodeslist }}訂購單</h1>
    <form action="/orderMenu" method="post">
    <label for="nos">{{ nodeslist }}數量</label>
    <input type="text" id="nos" placeholder="請輸入數量" name="nos">
    <br>
    <label for="cusphone">手機號碼</label>
    <input type="text" id="cusphone" placeholder="請輸入手機號碼" name="cusphone">
    <br>
    <input type="hidden" name="nodes" value="{{ nodeslist }}">
    <input type="submit" value="送出">
    </form>
    </div>
    </div>

    </div>
    {% endblock %}
  3. 新增訂單資料表:
    C:\workspace\LineBot> heroku login -i
    C:\workspace\LineBot> python
    >>> import os
    >>> import psycopg2
    >>> heroku_pgCLI = 'heroku config:get DATABASE_URL -a 你的APP名稱'
    >>> DATABASE_URL = os.popen(heroku_pgCLI).read()[:-1]
    >>> print(DATABASE_URL)
    >>> connection_db=psycopg2.connect(DATABASE_URL, sslmode='require')
    >>> cursor = connection_db.cursor()
    >>> SQL_cmd = '''CREATE TABLE ordermenu(
    ... order_id serial PRIMARY KEY,
    ... nodes VARCHAR (50) NOT NULL,
    ... nos INT NOT NULL,
    ... cusphone VARCHAR (20) NOT NULL
    ... );'''
    >>> cursor.execute(SQL_cmd)
    >>> connection_db.commit()
    >>> cursor.close()
    >>> connection_db.close()
    >>>
    
  4. 新增訂單列表:
    {% extends "base.html" %}
    {% block title %}大學麵店訂單系統{% endblock %}

    {% block main %}

    <!-- 宣告巨集 -->
    {% macro show_row(data, tag) -%}
    {% for menu in data %}
    <div class="row">
    {% if menu[4] == 'Action' %}
    {% for item in menu %}
    <div class="col">
    <{{ tag }}>{{ item }}</{{ tag }}>
    </div>
    {% endfor %}
    {% else %}
    {% for item in menu %}
    <div class="col">
    <{{ tag }}>{{ item }}</{{ tag }}>
    </div>
    {% endfor %}
    <div class="col">
    <button type="submit" value="{{ menu[0],menu[1] }}" name="deldata">刪除</button>
    </div>
    {% endif %}
    </div>
    {% endfor %}
    {%- endmacro %}
    <!-- 宣告結束 -->

    <div class="container my-5 py-5">
    <div class="row">
    <div class="rol">
    <h1>訂單列表</h1>
    </div>
    </div>
    <!-- 顯示菜單用 -->
    {% set cols = (("項次","菜單","數量","手機號碼","Action"),)%}

    {{ show_row(cols, "h2") }}
    <hr class="my-4">
    <form action="/delads" method="post">
    {{ show_row(menulist,"p") }}
    </form>
    <form action="/addOrders" method="get">
    <input type="submit" value="新增訂單">
    </form>
    </div>

    {% endblock %}
  5. 修改 app/dataSQL/connectDB:
    (前面略過....)
    def addOrders(text):
        DATABASE_URL = os.environ['DATABASE_URL']
        connection_db = psycopg2.connect(DATABASE_URL,sslmode='require')
        cursor = connection_db.cursor()
        data = text.split(',')
        table_columns = '(nos,cusphone,nodes)'
        SQL_cmd = f"""INSERT INTO ordermenu { table_columns } VALUES(%s,%s,%s);"""
        cursor.execute(SQL_cmd,(int(data[0]),str(data[1]),str(data[2])))
        connection_db.commit()
        cursor.close()
        connection_db.close()
        return text
    
    def showOrders():
        DATABASE_URL = os.environ['DATABASE_URL']
        connection_db = psycopg2.connect(DATABASE_URL,sslmode='require')
        cursor = connection_db.cursor()
        SQL_cmd = f"""SELECT * FROM ordermenu ORDER by order_id DESC limit 10;"""
        cursor.execute(SQL_cmd)
        connection_db.commit()
        raws = cursor.fetchall()
        data = []
        for raw in raws:
            data.append(raw)
        
        cursor.close()
        connection_db.close()
        return data
    
  6. 將資料表送上 Heroku 主機,進行測試!

2021年8月10日 星期二

推送廣告活動訊息

學習目標:
  • 利用己學過的知識,進行商業化活動!

建立廣告活動訊息資料庫
  1. 增加一個資料表 ads 存放訊息:
    C:\workspace\LineBot> heroku login -i
    C:\workspace\LineBot> python
    >>> import os
    >>> import psycopg2
    >>> heroku_pgCLI = 'heroku config:get DATABASE_URL -a 你的APP名稱'
    >>> DATABASE_URL = os.popen(heroku_pgCLI).read()[:-1]
    >>> print(DATABASE_URL)
    >>> connection_db=psycopg2.connect(DATABASE_URL, sslmode='require')
    >>> cursor = connection_db.cursor()
    >>> SQL_cmd = '''CREATE TABLE ads(
    ... ads_id serial PRIMARY KEY,
    ... adstitle VARCHAR (150) NOT NULL,
    ... adscontent TEXT NOT NULL,
    ... adspicname VARCHAR (150) NOT NULL
    ... );'''
    >>> cursor.execute(SQL_cmd)
    >>> connection_db.commit()
    >>> cursor.close()
    >>> connection_db.close()
    >>>
    
  2. 修改 app/dataSQL/connectDB.py,寫入一段顯示活動資料的SQL語法:
    def showAds():
        DATABASE_URL = os.environ['DATABASE_URL']
        connection_db = psycopg2.connect(DATABASE_URL,sslmode='require')
        cursor = connection_db.cursor()
        SQL_cmd = f"""SELECT * FROM ads ORDER by ads_id DESC limit 5;"""
        cursor.execute(SQL_cmd)
        connection_db.commit()
        raws = cursor.fetchall()
        data = []
        for raw in raws:
            data.append(raw)
        
        cursor.close()
        connection_db.close()
        return data  
     
  3. 修改 app/router.py 檔案,加入一段引導到活動列表的程式:
    # 顯示活動清單列表
    @app.route("/showads")
    def showads():
        adslists = connectDB.showAds()
        return render_template('showads.html',menulist=adslists)
    
  4. 增加一個顯示活動清單的 html 程式碼 app/templates/showads.html:
    {% extends "base.html" %}
    {% block title %}大學麵店活動通知系統{% endblock %}

    {% block main %}

    <!-- 宣告巨集 -->
    {% macro show_row(data, tag) -%}
    {% for menu in data %}
    <div class="row">
    {% if menu[4] == 'Action' %}
    {% for item in menu %}
    <div class="col">
    <{{ tag }}>{{ item }}</{{ tag }}>
    </div>
    {% endfor %}
    {% else %}
    {% for item in menu %}
    <div class="col">
    <{{ tag }}>{{ item }}</{{ tag }}>
    </div>
    {% endfor %}
    <div class="col">
    <button type="submit" value="{{ menu[0],menu[1] }}" name="deldata">刪除</button>
    </div>
    {% endif %}
    </div>
    {% endfor %}
    {%- endmacro %}
    <!-- 宣告結束 -->

    <div class="container my-5 py-5">
    <div class="row">
    <div class="rol">
    <h1>活動列表</h1>
    </div>
    </div>
    <!-- 顯示菜單用 -->
    {% set cols = (("項次","活動標題","活動內容","參考圖檔","Action"),)%}

    {{ show_row(cols, "h2") }}
    <hr class="my-4">
    <form action="/delmenu" method="post">
    {{ show_row(menulist,"p") }}
    </form>
    <form action="/addmenu" method="get">
    <input type="submit" value="新增活動">
    </form>
    </div>

    {% endblock %}
  5. 推送上 Heroku 專案!檢視一下成果!
  6. 修改 app/templates/showads.html 檔案內容,確定新增/刪改的路徑:
    {{ show_row(cols, "h2") }}
    <hr class="my-4">
    <form action="/delads" method="post">
    {{ show_row(menulist,"p") }}
    </form>
    <form action="/addads" method="get">
    <input type="submit" value="新增活動">
    </form>
  7. 修改 app/router.py 檔案內容,加上新增與刪除的程式碼:
    # 新增活動清單
    @app.route("/addads",methods = ['GET','POST'])
    def addads():
        if request.method == 'POST':
            return showads()
        else:
            return showads()
    # 刪除活動清單
    @app.route("/delads",methods = ['GET','POST'])
    def delads():
        if request.method == 'POST':
            print(request.form)
            data = ""
            data1 = ""
            for key, value in request.form.items():
                data = eval(''.join(value))
                data1 = str(data[0])+','+str(data[1])
                print(data1)
                connectDB.deleteAds(data1)
            return showads()
        else:
            return render_template("showads.html")
    
  8. 修改 app/dataSQL/connectDB.py 程式,加入下列程式碼:
    (前面略過....)
    def deleteAds(text):
        DATABASE_URL = os.environ['DATABASE_URL']
        connection_db = psycopg2.connect(DATABASE_URL,sslmode='require')
        cursor = connection_db.cursor()
        data = text.split(',')
        SQL_cmd = f"""DELETE FROM ads WHERE ads_id = %s;"""
        print(int(data[0]))
        cursor.execute(SQL_cmd,[int(data[0])])
        connection_db.commit()
        cursor.close()
        connection_db.close()
        return text
    
  9. 推送上 Heroku 專案!檢視一下成果!
  10. 增加一個填寫資料內容的檔案 app/templates/addads.html:
    {% extends "base.html" %}
    {% block title %}大學麵店活動訊息系統{% endblock %}
    {% block main %}
    <div class="container">
    <div class="row">
    <div class="col">
    <h1>新增活動訊息</h1>
    <form action="/addads" method="post">
    <label for="adstitle">訊息標題</label>
    <input type="text" id="adstitle" placeholder="請輸入訊息標題" name="adstitle">
    <br>
    <br>
    <label for="adscontent">訊息內容</label>
    <input type="text" id="adscontent" placeholder="請輸入訊息內容" name="adscontent">
    <br>
    <br>
    <label for="adspicname">圖片名稱</label>
    <input type="text" id="adspicname" placeholder="請輸入圖片名稱" name="adspicname">
    <br>
    <input type="submit" value="送出">
    </form>
    </div>
    </div>
    </div>
    {% endblock %}
  11. 修改檔案 app/timer.py:
    (前面略過....)
    @scheduleEvent.scheduled_job('interval',minutes=1)
    def timed_job():
        msg = connectDB.showAds()
        print(msg)
        line_bot_api.push_message("你的ID",TextSendMessage(text='test'))
    
  12. 修改檔案 app/dataSQL/connectDB.py:
    (前面略過....)
    def addads(text):
        DATABASE_URL = os.environ['DATABASE_URL']
        connection_db = psycopg2.connect(DATABASE_URL,sslmode='require')
        cursor = connection_db.cursor()
        data = text.split(',')
        table_columns = '(adsname,adscontent,adspicname)'
        SQL_cmd = f"""INSERT INTO menu { table_columns } VALUES(%s,%s,%s);"""
        cursor.execute(SQL_cmd,(str(data[0]),str(data[1]),str(data[2])))
        connection_db.commit()
        cursor.close()
        connection_db.close()
        return text
    
  13. 修改 add/router.py 檔案內容:
    (前面略過....)
    # 新增活動清單
    @app.route("/addads",methods = ['GET','POST'])
    def addads():
        if request.method == 'POST':
            print(request.form)
            data = ""
            for key,value in request.form.items():
                data += value
                data += ','
            data = data[:-1]
            connectDB.addads(data)
            return showads()
        else:
            return render_template("addads.html")
    (後面略過....)
    
  14. 推送上 Heroku 專案!

2021年8月8日 星期日

實作 Flask 框架連結資料庫的網站

學習目標:
  • 了解 Flask 框架連結資料庫的用法!
  • 實作網站CRUD功能!

Flask 框架連結資料庫
  1. 修改 app/router.py 內容,在檔尾增加下列程式內容:
    (前方略過....)
    # 導向查詢菜單內容的網頁
    @app.route("/showmenu")
    def showmenu():
        menulists = connectDB.showallMenu()
        return render_template("menu.html", menulist=menulists)
    
  2. 新增 app/templates/menu.html 檔案,內容如下:
    {% extends "base.html" %}
    {% block title %}大學麵店菜單系統{% endblock %}

    {% block main %}
    <div class="container my-5 py-5">
    <div class="row">
    <div class="rol">
    <h1>菜單列表</h1>
    </div>
    </div>

    {% for menu in menulist %}
    <div class="row">
    {% for item in menu %}
    <div class="col">
    <p>{{ item }}</p>
    </div>
    {% endfor %}
    </div>
    {% endfor %}
    </div>
    {% endblock %}
  3. 推送上 Heroku 專案!利用瀏覽器查看站台: https://你的app.herokuapp.com/showmenu
  4. 修改 app/templates/menu.html 檔案,增加巨集內容(macro)如下:
    {% extends "base.html" %}
    {% block title %}大學麵店菜單系統{% endblock %}

    {% block main %}

    <!-- 宣告巨集 -->
    {% macro show_row(data, tag) -%}
    {% for menu in data %}
    <div class="row">
    {% for item in menu %}
    <div class="col">
    <{{ tag }}>{{ item }}</{{ tag }}>
    </div>
    {% endfor %}
    </div>
    {% endfor %}
    {%- endmacro %}
    <!-- 宣告結束 -->

    <div class="container my-5 py-5">
    <div class="row">
    <div class="rol">
    <h1>菜單列表</h1>
    </div>
    </div>
    <!-- 顯示菜單用 -->
    {% set cols = (("菜單項次","菜單名稱","價錢/每碗"),)%}

    {{ show_row(cols, "h2") }}
    <hr class="my-4">
    {{ show_row(menulist,"p") }}
    </div>

    {% endblock %}
  5. 推送上 Heroku 專案!利用瀏覽器查看站台: https://你的app.herokuapp.com/showmenu

實作 CRUD 連結資料庫
  1. 新增 app/templates/addmenu.html 檔案,內容如下:
    <form action="/addmenu" method="post">
    <label for="menuname">菜單名稱</label>
    <input type="text" id="menuname" placeholder="請輸入菜單名稱" name="menuname">
    <br>
    <label for="menuprize">菜單價錢</label>
    <input type="text" id="menuprize" placeholder="請輸入價格" name="menuprize">
    <br>
    <input type="submit" value="送出">
    </form>
  2. 修改 app/router.py 內容,在檔尾增加下列程式內容:
    (前方略過....)
    # 新增菜單內容的網頁
    @app.route("/addmenu", methods=['GET', 'POST'])
    def addmenu():
        if request.method == 'POST':
            data = ""
            for key, value in request.form.items():
                print(value)
                data += value
                data += ','
            data = data[:-1]
            connectDB.addMenu(data)
            print(data)
            menulists = connectDB.showallMenu()
            return render_template("menu.html", menulist=menulists)
        else:
            return render_template("addmenu.html")
    
  3. 推送上 Heroku 專案!利用瀏覽器查看站台: https://你的app.herokuapp.com/showmenu
  4. 修改 app/router.py 內容,在檔尾增加下列程式內容:
    (前方略過....)
    # 刪除菜單內容的網頁
    @app.route("/delmenu", methods=['GET', 'POST'])
    def delmenu():
        if request.method == 'POST':
            print(request.form)
            data = ""
            data1 = ""
            for key, value in request.form.items():
                data = eval(''.join(value))
                data1 = str(data[0])+','+str(data[1])
                print(data1)
                connectDB.deleteMenu(data1)
    
        menulists = connectDB.showallMenu()
        return render_template("menu.html", menulist=menulists)
    
  5. 修改 app/templates/menu.html 檔案,內容如下:
    {% extends "base.html" %}
    {% block title %}大學麵店菜單系統{% endblock %}

    {% block main %}

    <!-- 宣告巨集 -->
    {% macro show_row(data, tag) -%}
    {% for menu in data %}
    <div class="row">
    {% if menu[3] == 'Action' %}
    {% for item in menu %}
    <div class="col">
    <{{ tag }}>{{ item }}</{{ tag }}>
    </div>
    {% endfor %}
    {% else %}
    {% for item in menu %}
    <div class="col">
    <{{ tag }}>{{ item }}</{{ tag }}>
    </div>
    {% endfor %}
    <div class="col">
    <button type="submit" value="{{ menu[1],menu[2] }}" name="deldata">刪除</button>
    </div>
    {% endif %}
    </div>
    {% endfor %}
    {%- endmacro %}
    <!-- 宣告結束 -->

    <div class="container my-5 py-5">
    <div class="row">
    <div class="rol">
    <h1>菜單列表</h1>
    </div>
    </div>
    <!-- 顯示菜單用 -->
    {% set cols = (("菜單項次","菜單名稱","價錢/每碗","Action"),)%}

    {{ show_row(cols, "h2") }}
    <hr class="my-4">
    <form action="/delmenu" method="post">
    {{ show_row(menulist,"p") }}
    </form>
    <form action="/addmenu" method="get">
    <input type="submit" value="新增菜單">
    </form>
    </div>

    {% endblock %}
  6. 推送上 Heroku 專案!利用瀏覽器查看站台: https://你的app.herokuapp.com/showmenu

2021年8月3日 星期二

利用 Flask 建立支援 Line Bot 的後勤網站

學習目標:
  • 了解 Flask 的用法!
  • 建立支援 Line Bot 機器人的網站!

利用 Bootstrap 製作 Flask Web 站台網頁
  1. 開啟 templates/home.html 檔案,導入 Bootstrap 連結:
    <!DOCTYPE html>
    <html lang="en">
    <head>
    <meta charset="utf-8">
    <meta name="viewport" content="width=device-width, initial-scale=1">
    <link href="https://cdn.jsdelivr.net/npm/bootstrap@5.0.2/dist/css/bootstrap.min.css" rel="stylesheet" integrity="sha384-EVSTQN3/azprG1Anm3QDgpJLIm9Nao0Yz1ztcQTwFspd3yD65VohhpuuCOmLASjC" crossorigin="anonymous">
    <title>MySite</title>
    </head>
    <body>
    Hello , Hacker !!
    <script src="https://cdn.jsdelivr.net/npm/bootstrap@5.0.2/dist/js/bootstrap.bundle.min.js" integrity="sha384-MrcW6ZMFYlzcLA8Nl+NtUVF0sA7MsXsP1UyJoMp4YLEuNSfAP+JcXn/tWtIaxVXM" crossorigin="anonymous"></script>
    </body>
    </html>
  2. 使用導航列!
    (前方略過....)
    <body>
    <nav class="navbar navbar-expand-sm navbar-dark bg-primary">
    <ul class="navbar-nav">
    <li class="nav-item">
    <a class="nav-link" href="#">Home</a>
    </li>
    <li class="nav-item">
    <a class="nav-link" href="#">Link</a>
    </li>
    </ul>
    </nav> (後方略過....)
  3. 使用拆疊式按鍵,方便做成 RWD 網頁
    (前方略過....)
    <body>
    <nav class="navbar navbar-expand-sm navbar-dark bg-primary">

    <button class="navbar-toggler" type="button" data-toggle="collapse" data-target="#collapsibleNavBar">
    <span class="navbar-toggler-icon"></span>
    </button>

    <div class="collapse navbar-collapse" id="collapsibleNavBar">
    <ul class="navbar-nav"> (後方略過....)
  4. 使用 Jumbotron
    (前方略過....)
    </nav>
    <div class="jumbotron">
    <h1>Hello , Hacker !!</h1>
    <p>這是測試頁...
    </div> (後方略過....)
  5. 使用 Google fonts :
    (前方略過....)
    <link rel="preconnect" href="https://fonts.googleapis.com">
    <link rel="preconnect" href="https://fonts.gstatic.com" crossorigin>
    <link href="https://fonts.googleapis.com/css2?family=Noto+Sans+TC:wght@300&display=swap" rel="stylesheet">

    <title>MySite</title>
    <style> body {font-family: 'Noto Sans TC', sans-serif;}</style>
    </head> (後方略過....)
利用 Jinja2 模板引擎打造網頁
  1. 將 home.html 檔案,複製到 base.html 檔案
  2. 修改 base.html 檔案中,可能異動的部份:
    (前方略過....)
    <title>{% block title %}{% endblock %}</title>
    (中間略過....) 
    <!--取代 jumbotron 那一段-->
    <main>
    {% block main %}{% endblock %}
    </main>

    <footer>
    </footer> (中間略過....) {% block script %}{% endblock %}
    </body>
  3. 修改 home.html 檔案,去掉重複的部份,並加入 base.html 樣板檔:
    {% extends "base.html" %}
    {% block title %}My Web Site{% endblock %}
    {% block main %}
    <div class="jumbotron">
    <h1>Hello , Hacker !!</h1>
    <p>這是測試頁...</p>
    </div>
    <div class="container my-5 py-5">
    <div class="row">
    <div class="col">
    <h2>左側</h2>
    </div>
    <div class="col">
    <h2>中間</h2>
    </div>
    <div class="col">
    <h2>右側</h2>
    </div>
    </div>
    </div>
    {% endblock %}
  4. 送上 Heroku 主機,測試看看內容!
  5. 修改 app/router.py 檔案內容,加入導向查詢菜單的網頁位置:
    # 導向查詢菜單內容的網頁
    app.route("/showmenu")
    def showmenu():
        return render_template("menu.html")
    
  6. 新增菜單的網頁 app/templates/menu.html:
    {% extends "base.html" %}
    {% block title %}大學麵店菜單系統{% endblock %}

    {% block main %}
    <div class="container my-5 py-5">
    <div class="row">
    <div class="rol">
    <h1>菜單列表</h1>
    </div>
    </div>

    {% for menu in menulist %}
    <div class="row">
    <div class="col">
    <p>{{ menu[0] }}</p>
    </div>
    <div class="col">
    <p>{{ menu[1] }}</p>
    </div>
    <div class="col">
    <p>{{ menu[2] }}</p>
    </div>
    </div>
    {% endfor %}
    </div>
    {% endblock %}
  7. 送上 Heroku 主機,測試看看內容!