0
0

話題のhtmxを試してみた

Posted at

話題のHTMXを試して見ました。
WebアプリケーションフレームワークはFlaskです。

HTMXを使った場合と使ってない場合を比較したかったので、最初にHTMXを使ってないアプリを作りました。以下はChatGPTさんに「ボタンを押下すると表示された数値がカウントされる、簡単なアプリの例をお願いします。」で生成したコードそのままです。

app.py
from flask import Flask, render_template_string, request, redirect, url_for

app = Flask(__name__)

# カウンターの値を保持する変数
counter = 0

# HTMLテンプレート
html = """
    <!doctype html>
    <html>
    <head><title>Counting App</title></head>
    <body>
        <h1>Counter: {{ counter }}</h1>
        <form action="/count" method="post">
            <input type="submit" value="Count">
        </form>
    </body>
    </html>
"""

@app.route('/')
def index():
    global counter
    return render_template_string(html, counter=counter)

@app.route('/count', methods=['POST'])
def count():
    global counter
    counter += 1  # ボタンが押されるたびにカウンターを増やす
    return redirect(url_for('index'))  # メインページにリダイレクト

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

実行すると以下のような画面になります。
py1.png

ボタンを押下するたびに1加算されます。
py1a.png

これだけだと面白くないかなと思い、+2されるボタンを追加して見ました。これはChatGPTさんでなく自分で変更。

app2.py
from flask import Flask, render_template_string, request, redirect, url_for

app = Flask(__name__)

# カウンターの値を保持する変数
counter = 0
counter2 = 0

# HTMLテンプレート
html = """
    <!doctype html>
    <html>
    <head><title>Counting App</title></head>
    <body>
        <h1>Counter: {{ counter }}</h1>
        <form action="/count" method="post">
            <input type="submit" value="Count">
        </form>
    </body>
    <body>
        <h1>Counter2: {{ counter2 }}</h1>
        <form action="/count2" method="post">
            <input type="submit" value="Count2">
        </form>
    </body>
    </html>
"""

@app.route('/')
def index():
    global counter
    global counter2
    return render_template_string(html, counter=counter, counter2=counter2)

@app.route('/count', methods=['POST'])
def count():
    global counter
    counter += 1  # ボタンが押されるたびにカウンターを増やす
    return redirect(url_for('index'))  # メインページにリダイレクト

@app.route('/count2', methods=['POST'])
def count2():
    global counter2
    counter2 += 2  # ボタンが押されるたびにカウンターを増やす
    return redirect(url_for('index'))  # メインページにリダイレクト

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

実行すると以下のような画面になります。
py2.png

上のボタンは押下するたびに1加算されます。下のボタンは押下するたびに2加算されます。
py2a.png

次はHTMXを使ったパターン。ここでまたまたChatGPTさんの登場。「app2.pyですが、HTMX使うとどうなりますか」と聞いて生成したのが下記のコード。

app3.py
from flask import Flask, render_template_string, request, jsonify

app = Flask(__name__)

# カウンターの値を保持する変数
counter = 0
counter2 = 0

# HTMLテンプレート
html = """
<!doctype html>
<html>
<head>
    <title>Counting App</title>
    <script src="https://unpkg.com/htmx.org"></script> <!-- HTMXライブラリを追加 -->
</head>
<body>
    <div id="counter1">
        <h1>Counter: {{ counter }}</h1>
        <form hx-post="/count" hx-target="#counter1" hx-swap="outerHTML">
            <input type="submit" value="Count">
        </form>
    </div>
    <div id="counter2">
        <h1>Counter2: {{ counter2 }}</h1>
        <form hx-post="/count2" hx-target="#counter2" hx-swap="outerHTML">
            <input type="submit" value="Count2">
        </form>
    </div>
</body>
</html>
"""

@app.route('/')
def index():
    global counter, counter2
    return render_template_string(html, counter=counter, counter2=counter2)

@app.route('/count', methods=['POST'])
def count():
    global counter
    counter += 1
    return render_template_string('<div id="counter1"><h1>Counter: {{ counter }}</h1><form hx-post="/count" hx-target="#counter1" hx-swap="outerHTML"><input type="submit" value="Count"></form></div>', counter=counter)

@app.route('/count2', methods=['POST'])
def count2():
    global counter2
    counter2 += 2
    return render_template_string('<div id="counter2"><h1>Counter2: {{ counter2 }}</h1><form hx-post="/count2" hx-target="#counter2" hx-swap="outerHTML"><input type="submit" value="Count2"></form></div>', counter2=counter2)

if __name__ == '__main__':
    app.run(debug=True)
"""

@app.route('/')
def index():
    global counter, counter2
    return render_template_string(html, counter=counter, counter2=counter2)

@app.route('/count', methods=['POST'])
def count():
    global counter
    counter += 1
    return render_template_string('<div id="counter1"><h1>Counter: {{ counter }}</h1><form hx-post="/count" hx-target="#counter1" hx-swap="outerHTML"><input type="submit" value="Count"></form></div>', counter=counter)

@app.route('/count2', methods=['POST'])
def count2():
    global counter2
    counter2 += 2
    return render_template_string('<div id="counter2"><h1>Counter2: {{ counter2 }}</h1><form hx-post="/count2" hx-target="#counter2" hx-swap="outerHTML"><input type="submit" value="Count2"></form></div>', counter2=counter2)

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

実行すると以下のような画面になります。

py3.png

こちらも上のボタンは押下するたびに1加算されます。下のボタンは押下するたびに2加算されます。見た目はapp2.pyと変わりませんが、ボタンを押下した時にページ全体がリロードされないので画面がチラチラしません。HTMXにした効果がちゃんと出ているようです。

py3a.png

最後に
実はWebアプリはあまりやったことがなくて、PythonとFlaskも初めて使いました。ChatGPTさんにこんなことやりたいのだけど、どうすりゃいいの? って聞きながら 。

0
0
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
0
0