見出し画像

AIと生きる~Cursorでアプリ開発 #11~

開発の続き

JSONの送受信でハマり、Flask公式ドキュメントを再読すると書きました。
以前、Webアプリを作成したときには、公式Tutorial部分を参考に作成し、他の部分は読んでいませんでした。
今回、公式ドキュメントを一読してみて、色々と気づきがありました。

  • 必ずしもJSONで送受信する必要が無いこと

  • app.pyで設定するルーティングについて

  • URLの基本的な仕組み

  • APIについて

などなど、Flaskの基本的な部分が理解できていなかったことに気づきました。
ハマっていた(ハマっていると思っていた)JSONの送受信も、自分が、
「ルーティングでこのページが表示されているはず」
と、思い込んで、URLアドレスの表示部分を見ておらず、
「そもそも意図したページが表示されていなかった」
ということが判明しました。
最大の気付きは、苦手で敬遠していた公式ドキュメントが少し読めるようになっていたことです。
季節の変わり目で、体調が良くない中で、文字だけを追うのは厳しい日が多くあったにも関わらず、一読したことで、
「どのあたりに、こんなことが書いていたな」
と、後からどこを見ればいいのか、大まかに把握できました。

修正をするところ

  • 顧客情報の新規登録⇒顧客管理ページ

  • メンテナンス情報の新規登録⇒メンテンス管理ページ

で作成していたところ、
「ページをいちいち切り替えないといけないのが面倒」
という意見をいただきました。
そこで、顧客情報もメンテナンス情報も、両方を新規登録する際は、下記のように、一連の流れでできるように修正をします。

  1. 新規登録用のページ(html)を新たに作成

  2. ページが表示されたら、顧客登録フォームを表示

  3. フォームへの入力

  4. 入力値の送信

  5. 成功したのかエラーなのかをメッセージ表示

  6. 顧客登録に成功したら、メンテナンス登録フォームを表示

  7. 登録した顧客IDを取得し、顧客ID欄に表示(これで紐づけ)

  8. フォームへの入力

  9. 入力値の送信

  10. 成功したのかエラーなのかをメッセージ表示

ハマったと思っていたのは、4.のところで、
新規登録ボタンがクリックされた際に、5.と6.を同一ページ上で処理をするのに、JavaScriptが必要となり、いつも通り、AIに指示(プロンプト)を投げて作成してもらったところ、JSONで送受信するコードになっていました。
実行すれどもすれども、意図した処理ができずに数日を費やす結果となったのは、前回の記事でお伝えしたとおりです。
ここで、Flask公式ドキュメントを一読し、最初に書いたとおりの状況となりました。

アプリの修正に戻る

体調不良も重なり、大雑把に一読したあと、アプリの修正を再開すると、気付けなかった初歩的なミスに気づき、Cursorの無料枠をまたまた使い果たしていたので、それをWindows Copilotで確認。

【自分の質問】
下記コードを実行しても、registration.htmlが再表示されず、http://127.0.0.1:5000/register_customerに
{ "message": "登録が完了しました" }
が表示される原因と解決策を教えて
(ココにhtmlとapp.pyのコードを貼付して質問を投げました)

【Copilotからの返答】
この問題は、HTMLフォームのデフォルトの動作が引き起こしています。フォームが送信されると、ブラウザはページをリロードし、フォームのaction属性で指定されたURLに移動します。この場合、そのURLは/register_customerで、その結果としてJSONレスポンスが表示されます。 これを解決するためには、JavaScriptのfetch関数を使用して非同期にフォームデータを送信し、そのレスポンスを処理する必要があります。以下に修正したコードを示します:
(ココにAI で生成されたコードが出力されました)
ご確認のうえ、慎重にご使用ください。FAQ で詳細を確認。 この修正により、フォームの送信がデフォルトの動作(ページのリロード)ではなく、Fetch APIを使用した非同期リクエストによって行われるようになります。これにより、サーバーからのJSONレスポンスを適切に処理できます。この修正により、コードの可読性と保守性が向上します。

修正を提案されたのは下記の部分

#html部分
#修正前
<form method="POST" action="{{ url_for('register_customer') }}">

#修正後
<form id="customerForm" method="POST">

action="{{ url_for('register_customer') }}"部分を削除しました。
id="customerForm"を追加しました。

#script部分

#修正前
$(document).ready(function() { 
    $.get('{{ url_for("register_customer") }}', function(data) { 
        console.log(data); 
        var message = JSON.parse(data); 
        console.log(message.message); }); });


#修正後
document.getElementById('customerForm').addEventListener('submit', function(event) {
        event.preventDefault();
        let data = new FormData(this);
        fetch('{{ url_for("register_customer") }}', {
            method: 'POST',
            body: data,
        })
        .then(response => response.json())
        .then(data => {
            switch(data.message) {
                case '登録が完了しました':
                    $('#newcustomerForm').hide();
                    alert('顧客情報の新規登録が完了しました。続いてメンテナンス情報を入力してください');
                    $('#maintenanceForm').show();
                    $('#customer_id2').val($('#customer_id').val());
                    break;
                case '既に登録されています':
                    alert('入力されたお客様情報は既に登録されています');
                    break;
                case 'データベースエラーが発生しました。登録に失敗しました。':
                    alert('データベースエラーが発生しました。登録に失敗しました。');
                    break;
                case 'フォームのバリデーションに失敗しました':
                    alert('エラー');
                    break;
                default:
                    alert('未知のメッセージ: ' + data.message);
            }
        });
    });

app.pyは正常に動作していたので、貼付していましたが、修正はありませんでした。
ただ、そのコードを受けて、script部分の修正に、メッセージにより条件分岐を追加してくれました。

#app.pyの該当箇所

#顧客新規登録のルーティング
@app.route('/register_customer', methods=['GET', 'POST'])
def register_customer():
    # form = CustomerForm()
    # maintenance_form = MaintenanceForm()
    # employees = Employee.query.all()

    # #メンテナンスフォームの受付者、担当者選択項目の設定
    # maintenance_form.recipient_id.choices = [('-1', '選択してください')] + [(employee.id, employee.name) for employee in employees]
    # maintenance_form.maintenance_person_id.choices = [('-1', '選択してください')] + [(employee.id, employee.name) for employee in employees]

    try:
        form = CustomerForm(request.form)
        if form.validate_on_submit():
            # フォームから送信されるデータから余分な空白を削除
            id = form.id.data.strip()
            name = form.name.data.strip()
            address = form.address.data.strip()
            telephone = form.telephone.data.strip()
            usage_number = form.usage_number.data.strip()

            existing_customer = Customer.query.filter_by(
                name=name, 
                address=address, 
                telephone=telephone, 
                usage_number=usage_number).first()
            if existing_customer:
                return jsonify({'message': '既に登録されています'})
            else:
                customer = Customer(
                    id=id,
                    name=name,
                    address=address,
                    telephone=telephone,
                    usage_number=usage_number
                )
                db.session.add(customer)
                db.session.commit()
                
                return jsonify({'message': '登録が完了しました'})
        else:
            return jsonify({'message': 'フォームのバリデーションに失敗しました'})
    except Exception as e:
        db.session.rollback()
        return jsonify({'message': 'データベースエラーが発生しました。登録に失敗しました。'})
    finally:
        db.session.close()

と、出力されたhtmlファイルの修正をコピペしたところ、無事に解決。
JSONの送受信でハマっていたのではなく、script部分の処理コードの問題でした。
はじめから、このURL表示に問題があると気づいていれば、指示(プロンプト)が適切に投げられるので、解決が早かったはずです。
メンテナンスフォームの表示とJavaScriptの処理も同様に記述し、あっさりと実装できました。
少し知識が増えたので、他のページも、見直してみようと思います。

新規登録ページの画面遷移

ナビバーに「新規登録」を追加
新規登録ページの最初の画面
顧客フォームを表示し、新規の顧客idを取得してID欄に表示する機能も追加


「新規登録ボタン」がクリックされ、登録が成功した画面
アラートメッセージも表示できている
「OK」をクリックすると、次の画面に遷移
メンテナンスフォームを表示
先ほど新規登録された顧客idを取得し、メンテナンスフォームの顧客IDに表示する機能も追加

今回のまとめ

  • どこに問題があるかを見抜く「眼」が重要

  • 生成AIは指示(プロンプト)が明確だと、きちんと返答する

今の体調

  • 頭痛

  • 関節痛

  • 強い倦怠感

  • 軽いふらつき

  • 強度の花粉症症状(目のかゆみ、鼻炎)

寒暖差など気候の急変動と、雨が多かったこともあり、気圧の関係でつらい日々が続きました。
思うような処理が実装できず、イライラしていました。
公式ドキュメントを読むことで、視点を変えることができたことと、流し読みでも、なんとなく理解できたので、視野が拡がりました。

いいなと思ったら応援しよう!