Python {Article076}

ようこそ「Python」へ...

PyScriptでSQLite3データベースのレコードを操作するには

この記事では、PyScriptを使用してSQLite3データベースにitemsテーブルを作成して新規レコードを作成する方法を解説しています。 さらに、レコードを更新、削除、抽出する方法についても説明しています。itemsテーブルから抽出したデータは表形式でWebページ上に表示します。 まずは、「GO LIVE DEMO」をクリックして「Live DEMO」をご覧ください。

Visual Studio Code(VSC)からHTMLファイルをブラウザに表示するには「Live Serer」を使用します。 「Live Server」のインストール手順は「記事(Article073)」で解説しています。

説明文の左側に図の画像が表示されていますが縮小されています。 画像を拡大するにはマウスを画像上に移動してクリックします。 画像が拡大表示されます。拡大された画像を閉じるには右上の[X]をクリックします。 画像の任意の場所をクリックして閉じることもできます。

click image to zoom!
図A: PyScript DEMO #1
click image to zoom!
図B: PyScript DEMO #2
click image to zoom!
図C: PyScript DEMO #3
click image to zoom!
図D: PyScript DEMO #4


SQLite3データベースにテーブルを作成してレコードを追加、更新、削除、抽出する

  1. 新規HTMLファイルを作成してCSSを追加する

    Visual Studio Code(VSC)を起動したら新規HTMLファイルを作成します。 HTMLファイルが表示されたら「!」を入力してポップアップリストから「先頭行」クリックします。 HTMLのテンプレートが表示されたら行7のtitleを書き換えます。 次に行8-21を入力してCSSを追加します。
    <!DOCTYPE html>
    <html lang="en">
    <head>
        <meta charset="UTF-8">
        <meta http-equiv="X-UA-Compatible" content="IE=edge">
        <meta name="viewport" content="width=device-width, initial-scale=1.0">
        <title>>How to manipulate records in a SQLite3 database with PyScript #1 🐍</title>  
        <style>      
            body {
              margin: 5% 5% !important;
            }      
            .h1_article076 {
                font-size:xx-large;
            }        
            .div_article076 {
              border-radius: 5px;
              color:coral;
              background-color: #f2f2f2;
              padding: 20px;
            }
        </style>    
        
    </head>
    <body>    
    
    </body>
    </html>

  2. headセクションにlink, scriptを追加してPyScriptのCSS, JavaScriptライブラリを取り込む

    headセクションに行22-28を追加します。 行22-23ではPyScript等のCSSを取り込んでいます。 行24ではPyScriptのJavScriptのライブラリを取り込んでいます。 行25-28ではPythonのライブラリを宣言しています。
    <!DOCTYPE html>
    <html lang="en">
    <head>
        <meta charset="UTF-8">
        <meta http-equiv="X-UA-Compatible" content="IE=edge">
        <meta name="viewport" content="width=device-width, initial-scale=1.0">
        <title>How to manipulate records in a SQLite3 database with PyScript #1 🐍</title>  
        <style>      
            body {
              margin: 5% 5% !important;
            }      
            .h1_article076 {
                font-size:xx-large;
            }        
            .div_article076 {
              border-radius: 5px;
              color:coral;
              background-color: #f2f2f2;
              padding: 20px;
            }
        </style>    
        <link rel='stylesheet' type='text/css' media='screen' href='https://cdn.jsdelivr.net/npm/bulma@0.9.3/css/bulma.min.css'>
        <link rel="stylesheet" href="https://pyscript.net/alpha/pyscript.css" />
        <script defer src="https://pyscript.net/alpha/pyscript.js"></script>        
        <py-env>
          - numpy
          - pandas
        </py-env>      
    </head>
    <body>    
    
    </body>
    </html>

  3. bodyセクションにHTMLのmain, h1, legend, input要素を配置する

    bodyセクションにmain, h1, legend, input, div要素を追加して配置します。 行9-16ではアイテムのId, Item Name, Quantity, Priceを入力するためのテキストボックスを配置しています。 行19-23ではアイテムを挿入、更新、削除、消去、抽出するためのボタンを配置しています。 これらのbutton要素には「pys-onClick」属性を追加してクリック時のイベントを設定しています。 ここで設定したクリック時のイベントは後述するステップで作成します。 行26のdiv#output要素にはSQLite3のitemsテーブルの内容を表示します。
    <!DOCTYPE html>
    <html lang="en">
    <head>
        :::     
    </head>
    <body>    
        <main>
            <h1 class="h1_article076">Manipulate records in a SQLite3 database with PyScript #1 🐍</h1>  
            <legend>Id</legend>
            <input type="number" class="from-control" name="" id="id" /> 
            <legend>Item Name</legend>
            <input type="text" class="form-control" name="" id="item" />
            <legend>Quantity</legend>
            <input type="number" class="from-control" name="" id="quantity" />       
            <legend>Unit Price</legend>
            <input type="number" class="from-control" name="" id="price" />           
            <hr />
            <br />
            <button id="insert" class="button is-primary" pys-onClick="insert_item">Insert</button>
            <button id="update" class="button is-primary" pys-onClick="update_item">Update</button>
            <button id="delete" class="button is-danger" pys-onClick="delete_item">Delete</button>
            <button id="clear" class="button is-primary" pys-onClick="clear_input">Clear</button>
            <button id="fetch" class="button is-primary" pys-onclick="fetch_record">Fetch Record</button>
            <hr />
            <br />
            <div id="output" class="div_article076"></div>   
        </main>
    
    </body>
    </html>

  4. bodyセクションにpy-scriptを追加してPythonのコードを追加する

    bodyセクションに<py-script>...</py-script>を追加してPythonのコードを記述します。 行31-33ではPythonのライブラリを取り込んでいます。 行35-36ではSQLite3のデータベースに接続してcursorを生成しています。 ここではconnect()メソッドの引数に「:memory:」を指定してデータベースをメモリ上に作成します。

    行39-46ではitemsテーブルを作成するためのSQLコマンドを定義しています。 ここではitemsテーブルを作成します。 行47ではcursorのexecute()メソッドをSQLコマンド実行しています。

    行50-57では関数「insert_item()」を定義しています。 この関数ではitemsテーブルに新規レコードを追加します。 行51-53ではHTMLのテキストボックス(input要素)から「item, qty, price」の情報を取得して変数に格納しています。 行54では新規レコードを追加するSQLコマンドを定義しています。 行55ではcursorのexecute()メソッドでSQLコマンドを実行しています。

    行59-67では関数「update_item()を定義しています。 この関数ではitemsテーブルのレコードを更新します。 行64ではレコードを更新するSQLコマンドを定義しています。 行65ではcursorのexecute()メソッドでSQLコマンドを実行しています。

    行69-74では関数「delete_item()」を定義しています。 この関数ではitemsテーブルからレコードを削除します。 行71ではレコードを削除するSQLコマンドを定義しています。 行72ではcursorのexecute()メソッドでSQLコマンドを実行しています。

    行76-81では関数「clear_input()」を定義しています。 この関数ではHTMLのテキストボックスの内容を消去します。

    行83-95では関数「fetch_record()」を定義しています。 この関数ではitemsテーブルの全レコードを抽出してブラウザに表示します。 行86ではitemsテーブルから全レコードを抽出するSQLコマンドを定義しています。 行87ではcursorのexecute()メソッドでSQLコマンドを実行しています。 行88-92のforループでは各レコードからフィールド(id, item, qty, price)の値を取り出してフォーマットして変数dataに格納しています。 行94ではPyScriptのwrite()メソッドでitemsテーブルの内容(変数data)をdiv#output要素に挿入してブラウザに表示します。
    <!DOCTYPE html>
    <html lang="en">
    <head>
        :::   
    </head>
    <body>    
        <main>
            <h1 class="h1_article076">Manipulate records in a SQLite3 database with PyScript #1 🐍</h1>  
            <legend>Id</legend>
            <input type="number" class="from-control" name="" id="id" /> 
            <legend>Item Name</legend>
            <input type="text" class="form-control" name="" id="item" />
            <legend>Quantity</legend>
            <input type="number" class="from-control" name="" id="quantity" />       
            <legend>Unit Price</legend>
            <input type="number" class="from-control" name="" id="price" />           
            <hr />
            <br />
            <button id="insert" class="button is-primary" pys-onClick="insert_item">Insert</button>
            <button id="update" class="button is-primary" pys-onClick="update_item">Update</button>
            <button id="delete" class="button is-danger" pys-onClick="delete_item">Delete</button>
            <button id="clear" class="button is-primary" pys-onClick="clear_input">Clear</button>
            <button id="fetch" class="button is-primary" pys-onclick="fetch_record">Fetch Record</button>
            <hr />
            <br />
            <div id="output" class="div_article076"></div>   
        </main>
        
        <py-script>
    console.log('Executing python script...')        
    import numpy as np
    import pandas as pd
    import sqlite3 
    
    con = sqlite3.connect(':memory:')
    c = con.cursor()
    console.log("Connected sqlite3 database(':memory:')")
    
    sql = '''
    CREATE TABLE items ( 
        id INTEGER NOT NULL PRIMARY KEY AUTOINCREMENT, 
        item TEXT NOT NULL, 
        qty INT NOT NULL, 
        price INT NOT NULL
        )
    '''
    c.execute(sql)
    console.log("Creating table {sql}...")
    
    def insert_item(*args, **kwargs):
        item = Element('item').element.value
        qty = Element('quantity').element.value
        price = Element('price').element.value
        sql = f"INSERT INTO items (item, qty, price) VALUES ('{item}', {qty}, {price})"
        c.execute(sql)
        con.commit()
        console.log(f"Inserting data {sql}...")
    
    def update_item(*args, **kwargs):
        id = Element('id').element.value    
        item = Element('item').element.value
        qty = Element('quantity').element.value
        price = Element('price').element.value
        sql = f"UPDATE items SET item='{item}', qty={qty}, price={price} WHERE id={id}"
        c.execute(sql)
        con.commit()
        console.log("Updating data {sql}...")
    
    def delete_item(*args, **kwargs):
        id = Element('id').element.value         
        sql = f"DELETE FROM items WHERE id={id}"        
        c.execute(sql)
        con.commit()
        console.log("Deleting data {sql}...")
        
    def clear_input(*args, **kwargs):
        Element('id').clear() 
        Element('item').clear()
        Element('quantity').clear()
        Element('price').clear() 
        console.log("Clearing input data...")    
    
    def fetch_record(*args, **kwargs):
        sp = ' '; br = '<br />'          
        data = f"id{sp*5}item{sp*5}qty{sp*5}price{br}"        
        sql = "SELECT * FROM items"        
        rows = c.execute(sql)    
        for row in rows:
            id = row[0]; item = row[1]; qty = int(row[2]); price = float(row[3])
            console.log(id, item, qty, price)
            rec = f"{id}{sp*5}{item}{sp*5}{qty}{sp*5}{price:,.2f}{br}"
            data += rec
       
        pyscript.write('output', data)        
        console.log(f"Feching data {sql}...")
        </py-script>
    </body>
    </html>

  5. HTMLファイルのすべてを掲載

    最後にここで解説したHTMLファイルのすべてを掲載しましたので参考にしてください。
    <!DOCTYPE html>
    <html lang="en">
    <head>
        <meta charset="UTF-8">
        <meta http-equiv="X-UA-Compatible" content="IE=edge">
        <meta name="viewport" content="width=device-width, initial-scale=1.0">
        <title>How to manipulate records in a SQLite3 database with PyScript #1 🐍</title>  
        <style>      
            body {
              margin: 5% 5% !important;
            }      
            .h1_article076 {
                font-size:xx-large;
            }        
            .div_article076 {
              border-radius: 5px;
              color:coral;
              background-color: #f2f2f2;
              padding: 20px;
            }
        </style>    
        <link rel='stylesheet' type='text/css' media='screen' href='https://cdn.jsdelivr.net/npm/bulma@0.9.3/css/bulma.min.css'>
        <link rel="stylesheet" href="https://pyscript.net/alpha/pyscript.css" />
        <script defer src="https://pyscript.net/alpha/pyscript.js"></script>        
        <py-env>
          - numpy
          - pandas
        </py-env>      
    </head>
    <body>    
        <main>
            <h1 class="h1_article076">Manipulate records in a SQLite3 database with PyScript #1 🐍</h1>  
            <legend>Id</legend>
            <input type="number" class="from-control" name="" id="id" /> 
            <legend>Item Name</legend>
            <input type="text" class="form-control" name="" id="item" />
            <legend>Quantity</legend>
            <input type="number" class="from-control" name="" id="quantity" />       
            <legend>Unit Price</legend>
            <input type="number" class="from-control" name="" id="price" />           
            <hr />
            <br />
            <button id="insert" class="button is-primary" pys-onClick="insert_item">Insert</button>
            <button id="update" class="button is-primary" pys-onClick="update_item">Update</button>
            <button id="delete" class="button is-danger" pys-onClick="delete_item">Delete</button>
            <button id="clear" class="button is-primary" pys-onClick="clear_input">Clear</button>
            <button id="fetch" class="button is-primary" pys-onclick="fetch_record">Fetch Record</button>
            <hr />
            <br />
            <div id="output" class="div_article076"></div>   
        </main>
        
        <py-script>
    console.log('Executing python script...')        
    import numpy as np
    import pandas as pd
    import sqlite3 
    
    con = sqlite3.connect(':memory:')
    c = con.cursor()
    console.log("Connected sqlite3 database(':memory:')")
    
    sql = '''
    CREATE TABLE items ( 
        id INTEGER NOT NULL PRIMARY KEY AUTOINCREMENT, 
        item TEXT NOT NULL, 
        qty INT NOT NULL, 
        price INT NOT NULL
        )
    '''
    c.execute(sql)
    console.log("Creating table {sql}...")
    
    def insert_item(*args, **kwargs):
        item = Element('item').element.value
        qty = Element('quantity').element.value
        price = Element('price').element.value
        sql = f"INSERT INTO items (item, qty, price) VALUES ('{item}', {qty}, {price})"
        c.execute(sql)
        con.commit()
        console.log(f"Inserting data {sql}...")
    
    def update_item(*args, **kwargs):
        id = Element('id').element.value    
        item = Element('item').element.value
        qty = Element('quantity').element.value
        price = Element('price').element.value
        sql = f"UPDATE items SET item='{item}', qty={qty}, price={price} WHERE id={id}"
        c.execute(sql)
        con.commit()
        console.log("Updating data {sql}...")
    
    def delete_item(*args, **kwargs):
        id = Element('id').element.value         
        sql = f"DELETE FROM items WHERE id={id}"        
        c.execute(sql)
        con.commit()
        console.log("Deleting data {sql}...")
        
    def clear_input(*args, **kwargs):
        Element('id').clear() 
        Element('item').clear()
        Element('quantity').clear()
        Element('price').clear() 
        console.log("Clearing input data...")    
    
    def fetch_record(*args, **kwargs):
        sp = ' '; br = '<br />'          
        data = f"id{sp*5}item{sp*5}qty{sp*5}price{br}"        
        sql = "SELECT * FROM items"        
        rows = c.execute(sql)    
        for row in rows:
            id = row[0]; item = row[1]; qty = int(row[2]); price = float(row[3])
            console.log(id, item, qty, price)
            rec = f"{id}{sp*5}{item}{sp*5}{qty}{sp*5}{price:,.2f}{br}"
            data += rec
       
        pyscript.write('output', data)        
        console.log(f"Feching data {sql}...")
        </py-script>
    </body>
    </html>

  6. HTMLファイルをブラウザに表示する

    Visual Studo Code(VSC)からHTMLファイルをブラウザに表示するには、「Live Server」を使用します。 「Live Server」のインストールと操作については「記事(Article073)」で解説しています。 VSCから「Explorer」アイコンをクリックしてHTMLファイルの一覧を表示します。 一覧からHTMLファイルを右クリックしてポップアップリストから先頭の「Open with Live Server」をクリックします。
    click image to zoom!
    図1-1
    テキストボックスに「アイテム名、数量、単価」を入力したら[Insert]ボタンをクリックします。 itemsテーブルの内容を表示するには[Fetch Record]ボタンをクリックします。 ここでは「item1」を追加しています。「Id」はSQLite3が自動採番するので入力不要です。


    click image to zoom!
    図1-2
    ここではitemsテーブルから「item2」を削除しています。 Idのテキストボックスに「2」を入力したら[Delete]ボタンをクリックしてレコードを削除します。 [Fetch Record]ボタンをクリックすると最新のitemsテーブルの内容が表示されます。


    click image to zoom!
    図1-3
    ここではitemsテーブルの「item3」の情報を修正しています。 [Fetch Record]ボタンをクリックすると最新のitemsテーブルの内容が表示されます。


SQLite3のテーブルの内容を表形式で表示する

  1. itemsテーブルの内容を表形式で表示する

    ここでは前出のHTMLファイルに修正を加えてitemsテーブルの内容を表形式(Tabulator)で表示するように改善します。 headセクションに行16-26を追加してJavaScriptの各種ライブラリを取り込みます。 さらに、行33を追加してpanerlのライブラリを宣言します。

    bodyセクションの「div#output」要素を「div#table」要素に書き換えます。

    行65-67を追加してPythonのライブラリを取り込みます。 行84-86を追加して「div#table」要素ににTabulator要素を挿入します。 行121-126の関数「fetch_record」を書き換えてitemsテーブルの内容を表形式で表示します。 行123ではPandasのread_sql()メソッドでSQLite3のitemsテーブルから全レコードを抽出してDataFrameに格納しています。 行124ではTabulatorにDataFrameの内容を設定してブラウザに表示しています。
    <!DOCTYPE html>
    <html lang="en">
    <head>
        <meta charset="UTF-8">
        <meta http-equiv="X-UA-Compatible" content="IE=edge">
        <meta name="viewport" content="width=device-width, initial-scale=1.0">
        <title>How to manipulate records in a SQLite3 database with PyScript #2 🐍</title>  
        <style>      
            body {
              margin: 5% 5% !important;
            }      
            .h1_article076 {
                font-size:xx-large;
            }        
        </style>
        <script type="text/javascript" src="https://cdn.jsdelivr.net/npm/vega@5"></script>
        <script type="text/javascript" src="https://cdn.jsdelivr.net/npm/vega-lite@5"></script>
        <script type="text/javascript" src="https://cdn.jsdelivr.net/npm/vega-embed@6"></script>
        <script type="text/javascript" src="https://unpkg.com/tabulator-tables@4.9.3/dist/js/tabulator.js"></script>
        <script type="text/javascript" src="https://cdn.bokeh.org/bokeh/release/bokeh-2.4.2.js"></script>
        <script type="text/javascript" src="https://cdn.bokeh.org/bokeh/release/bokeh-widgets-2.4.2.min.js"></script>
        <script type="text/javascript" src="https://cdn.bokeh.org/bokeh/release/bokeh-tables-2.4.2.min.js"></script>
        <script type="text/javascript" src="https://unpkg.com/@holoviz/panel@0.13.0/dist/panel.min.js"></script>
        <script type="text/javascript">
            Bokeh.set_log_level("info");
        </script>             
        <link rel='stylesheet' type='text/css' media='screen' href='https://cdn.jsdelivr.net/npm/bulma@0.9.3/css/bulma.min.css'>
        <link rel="stylesheet" href="https://pyscript.net/alpha/pyscript.css" />
        <script defer src="https://pyscript.net/alpha/pyscript.js"></script>        
        <py-env>
          - numpy
          - pandas
          - panel==0.13.1a2
        </py-env>      
    </head>
    <body>     
        <main>
            <h1 class="h1_article076">Manipulate records in a SQLite3 database with PyScript #2 🐍</h1> 
            <legend>Id</legend>
            <input type="number" class="from-control" name="" id="id" /> 
            <legend>Item Name</legend>
            <input type="text" class="form-control" name="" id="item" />
            <legend>Quantity</legend>
            <input type="number" class="from-control" name="" id="quantity" />       
            <legend>Unit Price</legend>
            <input type="number" class="from-control" name="" id="price" />           
            <hr />
            <br />
            <button id="insert" class="button is-primary" pys-onClick="insert_item">Insert</button>
            <button id="update" class="button is-primary" pys-onClick="update_item">Update</button>
            <button id="delete" class="button is-danger" pys-onClick="delete_item">Delete</button>
            <button id="clear" class="button is-primary" pys-onClick="clear_input">Clear</button>
            <button id="fetch" class="button is-primary" pys-onclick="fetch_record">Fetch Record</button>
            <hr />
            <br />
            <div id="table"></div>  
        </main>
        
        <py-script>
    console.log('Executing python script...')        
    import numpy as np
    import pandas as pd
    import sqlite3 
    
    import asyncio
    import panel as pn
    from panel.io.pyodide import show
    
    con = sqlite3.connect(':memory:')
    c = con.cursor()
    console.log("Connected sqlite3 database(':memory:')")
    
    sql = '''
    CREATE TABLE items ( 
        id INTEGER NOT NULL PRIMARY KEY AUTOINCREMENT, 
        item TEXT NOT NULL, 
        qty INT NOT NULL, 
        price INT NOT NULL
        )
    '''
    c.execute(sql)
    console.log("Creating table {sql}...")
    
    table = pn.widgets.Tabulator(pagination='remote', page_size=10)
    document.getElementById('table').style.display = 'none'
    await show(table, 'table')
    
    def insert_item(*args, **kwargs):
        item = Element('item').element.value
        qty = Element('quantity').element.value
        price = Element('price').element.value
        sql = f"INSERT INTO items (item, qty, price) VALUES ('{item}', {qty}, {price})"
        c.execute(sql)
        con.commit()
        console.log(f"Inserting data {sql}...")
    
    def update_item(*args, **kwargs):
        id = Element('id').element.value    
        item = Element('item').element.value
        qty = Element('quantity').element.value
        price = Element('price').element.value
        sql = f"UPDATE items SET item='{item}', qty={qty}, price={price} WHERE id={id}"
        c.execute(sql)
        con.commit()
        console.log("Updating data {sql}...")
    
    def delete_item(*args, **kwargs):
        id = Element('id').element.value         
        sql = f"DELETE FROM items WHERE id={id}"        
        c.execute(sql)
        con.commit()
        console.log("Deleting data {sql}...")
        
    def clear_input(*args, **kwargs):
        Element('id').clear() 
        Element('item').clear()
        Element('quantity').clear()
        Element('price').clear() 
        console.log("Clearing input data...")    
    
    def fetch_record(*args, **kwargs):
        sql = "SELECT * FROM items" 
        df = pd.read_sql(sql, con)
        table.value = df
        document.getElementById('table').style.display = 'block'        
        console.log(f"Feching data {sql}...")
        </py-script>
    </body>
    </html>
    click image to zoom!
    図2
    ここではSQLite3のitemsテーブルに格納されているデータを表形式で表示しています。


Pythonのクラスファイルを取り込む

  1. Pythonのクラスファイルを作成する

    ここでは前出のPythonのコードをクラスファイルとメインファイルに分割します。 新規のPythonファイル「article076_item.py」を作成したら行2-37をコピペします。 行2-4ではPythonのライブラリを取り込んでいます。 行6ではPythonのクラス「item」を作成しています。 行7-9ではクラスの初期化用メソッド「__init__()」を定義しています。 このメソッドはクラス(item)のインスタンスを生成するときに呼び出されます。 行11-15ではクラスのメソッド「item_insert()」を定義しています。 行17-21ではクラスのメソッド「item_update()」を定義しています。 行23-27ではクラスのメソッド「item_delete()」を定義しています。 行29-32ではクラスのメソッド「item_fetch()」を定義しています。 行34-37ではクラスのメソッド「item_featchall()」を定義しています。
    article076_item.py:
    import numpy as np
    import pandas as pd
    import sqlite3
    
    class item:
        def __init__(self, con, cursor):
            self.con = con
            self.cursor = cursor
    
        def item_insert(self, item_name, qty, price):
            sql = f"INSERT INTO items (item, qty, price) VALUES ('{item_name}', {qty}, {price})"        
            row_count = self.cursor.execute(sql).rowcount
            self.con.commit()
            return row_count
    
        def item_update(self, id, item_name, qty, price):
            sql = f"UPDATE items SET item='{item_name}', qty={qty}, price={price} WHERE id={id}"
            row_count = self.cursor.execute(sql).rowcount
            self.con.commit()
            return row_count        
    
        def item_delete(self, id):
            sql = f"DELETE FROM items WHERE id={id}"
            row_count = self.cursor.execute(sql).rowcount
            self.con.commit()
            return row_count         
    
        def item_fetch(self, id):
            sql = f"SELECT * FROM items WHERE id={id}"
            df = pd.read_sql(sql, self.con)
            return df        
    
        def item_fetchall(self):
            sql = f"SELECT * FROM items"
            df = pd.read_sql(sql, self.con)
            return df
  2. Pythonのメインファイルを作成する

    Pythonの新規ファイル「article076_main.py」を作成したら行2-73をコピペします。 行3-9ではPythonのライブラリを取り込んでいます。 行13ではSQLite3のconnect()メソッドでデータベースを接続しています。 行14ではconnectのcusrsor()メソッドでcursorを生成しています。 行17-24では新規テーブルを作成するSQLコマンドを定義しています。 行25ではcusorのexecute()メソッドで新規テーブル(items)を作成しています。 行28ではitemクラスのインスタンスを生成しています。 引数にはSQLite3のconnectionとcursorのオブジェクトを指定します。

    行42-73ではHTMLの各種ボタンをクリックしたときに呼び出されるイベントを定義しています。 行46ではitemクラスの「item_insert()」メソッドを呼び出しています。 行54ではitemクラスの「item_update()」メソッドを呼び出しています。 行59ではitemクラスの「item_delete()」メソッドを呼び出しています。 行70ではitemクラスの「item_fetchall()」メソッドを呼び出しています。
    article076_main.py:
    console.log('Executing python script...')        
    import numpy as np
    import pandas as pd
    import sqlite3 
    
    import asyncio
    import panel as pn
    from panel.io.pyodide import show
    
    from article076_item import item
    
    con = sqlite3.connect(':memory:')
    cursor = con.cursor()
    console.log("Connected sqlite3 database(':memory:')")
    
    sql = '''
    CREATE TABLE items ( 
        id INTEGER NOT NULL PRIMARY KEY AUTOINCREMENT, 
        item TEXT NOT NULL, 
        qty INT NOT NULL, 
        price INT NOT NULL
        )
    '''
    cursor.execute(sql)
    console.log("Creating table {sql}...")
    
    o_item = item(con, cursor)
    console.log("initiated item class...")
    
    # item_name = 'ITEM-1'
    # qty = 1
    # price = 100.99
    # rows_affected = o_item.item_insert(item_name, qty, price) 
    # console.log(f"Inserting data {rows_affected}...")
    
    table = pn.widgets.Tabulator(pagination='remote', page_size=10)
    # hide pagination 'First, Prev [1][2][3] Next, Last'
    document.getElementById('table').style.display = 'none'
    await show(table, 'table')
    
    def insert_item(*args, **kwargs):
        item_name = Element('item').element.value
        qty = Element('quantity').element.value
        price = Element('price').element.value
        rows_affected = o_item.item_insert(item_name, qty, price) 
        console.log(f"Inserting data {rows_affected}...")
    
    def update_item(*args, **kwargs):
        id = Element('id').element.value    
        item_name = Element('item').element.value
        qty = Element('quantity').element.value
        price = Element('price').element.value
        rows_affected = o_item.item_update(id, item_name, qty, price)
        console.log("Updating data {rows_affected}...")
    
    def delete_item(*args, **kwargs):
        id = Element('id').element.value         
        rows_affected = o_item.item_delete(id)
        console.log("Deleting data {rows_affected}...")
        
    def clear_input(*args, **kwargs):
        Element('id').clear() 
        Element('item').clear()
        Element('quantity').clear()
        Element('price').clear() 
        console.log("Clearing input data...")    
    
    def fetch_record(*args, **kwargs):
        df = o_item.item_fetchall()
        table.value = df
        document.getElementById('table').style.display = 'block'    
        console.log(f"Feching data df.shape={df.shape}...")
  3. HTMLファイルにPythonのクラスとメインファイルを取り込む

    ここでは前出のHTMLファイルからPythonのコードを削除して外部ファイルから取り込むようにします。 headセクションに行34-35を追加してPythonのクラスファイル「article076_item.py」のパスを宣言します。 bodyセクションからPythonのコードを削除したらpy_script要素に「src=」属性を追加してPythonのメインファイル「article076_main.py」のパスを設定します。 これでHTMLファイルからPythonのコードを外部ファイルに移動することができました。 「Live DEMO」に移動してデモを操作して見てください。
    <!DOCTYPE html>
    <html lang="en">
    <head>
        <meta charset="UTF-8">
        <meta http-equiv="X-UA-Compatible" content="IE=edge">
        <meta name="viewport" content="width=device-width, initial-scale=1.0">
        <title>How to manipulate records in a SQLite3 database with PyScript #3 🐍</title>  
        <style>      
            body {
              margin: 5% 5% !important;
            }      
            .h1_article076 {
                font-size:xx-large;
            }        
        </style>
        <script type="text/javascript" src="https://cdn.jsdelivr.net/npm/vega@5"></script>
        <script type="text/javascript" src="https://cdn.jsdelivr.net/npm/vega-lite@5"></script>
        <script type="text/javascript" src="https://cdn.jsdelivr.net/npm/vega-embed@6"></script>
        <script type="text/javascript" src="https://unpkg.com/tabulator-tables@4.9.3/dist/js/tabulator.js"></script>
        <script type="text/javascript" src="https://cdn.bokeh.org/bokeh/release/bokeh-2.4.2.js"></script>
        <script type="text/javascript" src="https://cdn.bokeh.org/bokeh/release/bokeh-widgets-2.4.2.min.js"></script>
        <script type="text/javascript" src="https://cdn.bokeh.org/bokeh/release/bokeh-tables-2.4.2.min.js"></script>
        <script type="text/javascript" src="https://unpkg.com/@holoviz/panel@0.13.0/dist/panel.min.js"></script>
        <script type="text/javascript">
            Bokeh.set_log_level("info");
        </script>      
        <link rel='stylesheet' type='text/css' media='screen' href='https://cdn.jsdelivr.net/npm/bulma@0.9.3/css/bulma.min.css'>
        <link rel="stylesheet" href="https://pyscript.net/alpha/pyscript.css" />
        <script defer src="https://pyscript.net/alpha/pyscript.js"></script>        
        <py-env>
          - numpy
          - pandas
          - panel==0.13.1a2
          - paths:
            - ./python/article076_item.py
        </py-env>      
    </head>
    <body>     
        <main>
            <h1 class="h1_article076">Manipulate records in a SQLite3 database with PyScript #3 🐍</h1>    
            <legend>Id</legend>
            <input type="number" class="from-control" name="" id="id" /> 
            <legend>Item Name</legend>
            <input type="text" class="form-control" name="" id="item" />
            <legend>Quantity</legend>
            <input type="number" class="from-control" name="" id="quantity" />       
            <legend>Unit Price</legend>
            <input type="number" class="from-control" name="" id="price" />              
            <hr />    
            <br />     
            <button id="insert" class="button is-primary" pys-onClick="insert_item">Insert</button>
            <button id="update" class="button is-primary" pys-onClick="update_item">Update</button>
            <button id="delete" class="button is-danger" pys-onClick="delete_item">Delete</button>
            <button id="clear" class="button is-primary" pys-onClick="clear_input">Clear</button>
            <button id="fetch" class="button is-primary" pys-onclick="fetch_record">Fetch Record</button>   
            <hr />
            <br />
            <div id="table"></div>        
        </main>
        
        <py-script src="./python/article076_main.py"></py-script>
    </body>
    </html>

Live DEMO

注:この「Live DEMO」はスマホでは正常に動作しないことがありますのでパソコンでご覧ください。 テキストボックスにアイテム情報を入力したら[Insert]ボタンをクリックしてテーブルに挿入します。 テーブルの内容は[Fetch Record]ボタンをクリックすると表示されます。