11-Flask

Flask(Part.36)| 【商品管理アプリケーションの修正(】

python| まとめ | 現役エンジニア&プログラミングスクール講師「python」のまとめページです。pythonに関して抑えておきたい知識や文法やにについて記事をまとめています。まとめページの下部には「おすすめの学習書籍」「おすすめのITスクール情報」「おすすめ求人サイト」について情報を掲載中...

目標

  • 商品編集時に以前の商品名や価格をテキストボックスへ表示させる
  • アプリケーション内の画像を選択できるようにする
  • 商品に「販売中」「完売」「在庫切れ」「販売中止」ステータスを作成して「完売」「在庫切れ」は選択不可とし、「販売中止」は表示しない

商品管理アプリケーションの修正

商品管理アプリケーション修正

ここからは、これまで、商品管理アプリケーションで不便と感じていた部分について修正を行います。具体的には次の通りです。

  1. 商品一覧の編集ボタンをクリックしたときに、表示される編集画面で、編集前の商品名、価格、カテゴリーを初期値でセットさせます。
    (Git では release-products-001 ブランチで修正)
  2. 商品編集で画像をアップロードする以外に、既にアップロード済みの画像からも画像を選択できるようにします。
    (Git では release-products-002 ブランチで修正)
  3. 商品に「販売中」「完売」「在庫切れ」「販売中止」ステータスを作成して「完売」「在庫切れ」は選択不可とし、「販売中止」は表示しないようにします。
    (Git では release-products-003 ブランチで修正)

release-productsブランチの作成

商品管理アプリケーションは既に基本となる構成については作成を完了しています。このように、機能の追加漏れがあるような場合は、再度、featureブランチを作成するよりも、releaseブランチとしてブランチを作成して作業を行うのが一般的です。

Git Bushを立ち上げるとプロンプトの右側に(develop)と表示され、現在のブランチがdevelopブランチであることが分かります。(次の表示はVisual Studio CodeのGit Bushのプロンプトです。)

User@dellDevice MINGW64 ~/Desktop/FlaskProj (develop)

次のようにコマンドを入力していきます。次のように表示されるはずです。
$ git status

$ git checkout -b release-products-001

$ git status

商品管理アプリケーションの修正(release-products-001)

app.pyの編集(productsapp内)

app.pyファイルの 「edit_product」関数を次のように編集します。

# ルート: 商品を編集
@products_bp.route("/product/edit/<int:product_id>", methods=["GET", "POST"])
def edit_product(product_id):
    product = Product.query.get_or_404(product_id)
    form = AddProductForm(obj=product)
    form.set_category_choices()
    # 編集の場合、該当するカテゴリーをデフォルトで選択
    form.category.data = product.category_id

    if form.validate_on_submit():
        product.name = form.product_name.data
        product.price = form.product_price.data
        product.category_id = form.category.data

        # 画像のアップロード処理
        if "product_image" in request.files:
            image = request.files["product_image"]
            if image and allowed_file(image.filename):
                filename = secure_filename(image.filename)
                image_path = os.path.join(current_app.config["UPLOAD_FOLDER"], filename)

                # もしすでに画像があれば削除
                if product.image_url and product.image_url != "images/noimage.png":
                    old_image_path = os.path.join(
                        current_app.config["UPLOAD_FOLDER"],
                        os.path.basename(product.image_url),
                    )
                    if os.path.exists(old_image_path):
                        os.remove(old_image_path)

                # 新しい画像を保存
                image.save(image_path)
                product.image_url = f"images/{filename}"  # 新しい画像URLを保存

        db.session.commit()
        flash("商品情報を更新しました", "success")
        return redirect(url_for("products.product_list"))

    return render_template(
        "product_form.html", form=form, title="商品編集", product=product
    )

追加したのは次のプログラムです。

    # 編集の場合、該当するカテゴリーをデフォルトで選択
    form.category.data = product.category_id

これは、set_category_choices() メソッドで設定したカテゴリーのセレクトフィールド( form.category.choices)の中から初期値として表示したい値を取得する部分です。

うまくカテゴリーを選択させるには、セレクトフィールドの設定→該当するIDの取得→そのIDに関連する名前と順番にプログラムを記述する必要があります。

この部分の具体的な記述は、以下の通りです。

  1. form.set_category_choices()
  2. form.category.data = product.category_id
  3. product.category_id = form.category.data

product_form.htmlの編集(productsapp/templates内)

product_form.html を次のように編集します。

{% extends "base.html" %}

{% block title %}{{ title }}{% endblock %}

{% block header %}
<ul>
    <li><a href="{{ url_for('products.manage_products') }}" class="button-link">商品管理ページ</a></li>
    <li><a href="{{ url_for('products.product_list') }}" class="button-link">商品一覧に戻る</a></li>
</ul>
{% endblock %}
{% block content %}
<h1>{{ title }}</h1>

<form method="POST"
    action="{{ url_for('products.edit_product', product_id=product.id) if product else url_for('products.add_product') }}"
    enctype="multipart/form-data">

    {{ form.hidden_tag() }} <!-- CSRFトークンを含めるため -->

    <label for="product_name">商品名</label>
    {{ form.product_name(value=product.name if product else '') }} <!-- 商品名入力フィールド -->
    {% if form.product_name.errors %}
    <ul>
        {% for error in form.product_name.errors %}
        <li>{{ error }}</li>
        {% endfor %}
    </ul>
    {% endif %}

    <label for="product_price">価格</label>
    {{ form.product_price(value=product.price if product else '') }} <!-- 価格入力フィールド -->
    {% if form.product_price.errors %}
    <ul>
        {% for error in form.product_price.errors %}
        <li>{{ error }}</li>
        {% endfor %}
    </ul>
    {% endif %}

    <label for="category">カテゴリー</label>
    {{ form.category() }}
    {% if form.category.errors %}
    <ul>
        {% for error in form.category.errors %}
        <li>{{ error }}</li>
        {% endfor %}
    </ul>
    {% endif %}

    <label for="product_image">商品画像</label>
    <!-- 既存の画像がある場合は表示 -->
    {% if product and product.image_url %}
    <div>
        <img src="{{ url_for('products.static', filename=product.image_url) }}" alt="現在の画像"
            style="width: 100px; height: 100px;">
        <p>※新しい画像を選択すると上書きされます</p>
    </div>
    {% endif %}
    <label for="product_image" class="file-upload-label">画像を選択</label>
    <input type="file" id="product_image" name="product_image" accept="image/*">

    <input type="submit" value="商品を登録する">
</form>
<script>
    document.getElementById("product_image").addEventListener("change", function () {
        const fileName = this.files.length > 0 ? this.files[0].name : "画像を選択";
        document.querySelector(".file-upload-label").textContent = fileName;
    });
</script>

{% endblock %}

追加された部分は次の通りです。

<label for="product_name">商品名</label>
    {{ form.product_name(value=product.name if product else '') }} <!-- 修正部分 -->
<label for="product_price">価格</label>
    {{ form.product_price(value=product.price if product else '') }} <!-- 修正部分 -->
    <label for="category">カテゴリー</label>
    {{ form.category() }}  <!-- 修正部分 -->
    {% if form.category.errors %}
    <ul>
        {% for error in form.category.errors %}
        <li>{{ error }}</li>
        {% endfor %}
    </ul>
    {% endif %}

http://127.0.0.1:5000/products/manage_productsにアクセスします。

商品一覧をクリックします。

任意の商品の「編集」をクリックします。今回は「酎ハイ」と「プリン」で確認します。

「酎ハイ」の「編集」をクリックすと商品名に「酎ハイ」、価格に「450」、カテゴリーに「アルコール」がセットされます。

金額を「480」に変更して「商品を登録する」をクリックします。次のように変更されます。

続けて、「プリン」の「編集」をクリックします。商品名に「プリン」、価格に「500」、カテゴリーに「デザート」がセットされます。

コミット作業とrelease-productsブランチの削除

作業が完了したので「release-products-001」ブランチを「develop」ブランチにマジして、「release-products-001」ブランチは削除していきます。

git statusコマンドでファイルの状態を確認します。

git add .コマンドを入力します。

再度、git statusコマンドを入力します。

git commitコマンドを入力します。

Fix:商品管理アプリケーションの修正-001(20250323)

今回は設計書などはないため、設計書番号などの提示はなし。商品一覧の編集ボタンをクリックしたときに、表示される編集画面で、編集前の商品名、価格、カテゴリーが初期値でセットされるように修正を行っています。

上書き保存をして「COMMIT_EDITMSG」ファイルを閉じるとコミットが完了します。

vim や nano で開いている場合は操作が異なります。vi や vim では escキーを押し、コマンドモードに切り替えて :wq を入力し Enterキー を押下します。nanoでは「Ctrl + O」で上書き保存されます。
(※上キャプチャはvimエディタ)

developブランチへのマージ

コミットしたrelease-products-001ブランチをdevelopブランチへマージします。

git checkout developコマンドで、ブランチをdevelopブランチへ切り替えます。

git merge release-products-001コマンドで release-products-001ブランチの内容をdevelopブランチへマージします。

release-products-001ブランチの削除

developブランチへのマージが完了したら、release-products-001ブランチを削除します。

git branch -d release-products-001コマンドでrelease-products-001ブランチを削除します。

今回は以上になります。

「python」おすすめ書籍 ベスト3 | 現役エンジニア&プログラミングスクール講師「python」の学習でお勧めしたい書籍をご紹介しています。お勧めする理由としては、考え方、イメージなどを適切に捉えていること、「生のpython」に焦点をあてて解説をしている書籍であることなどが理由です。勿論、この他にも良い書籍はありますが、特に質の高かったものを選んで記事にしています。ページの下部には「おすすめのITスクール情報」「おすすめ求人サイト」について情報を掲載中。...

ブックマークのすすめ

「ほわほわぶろぐ」を常に検索するのが面倒だという方はブックマークをお勧めします。ブックマークの設定は別記事にて掲載しています。

「お気に入り」の登録・削除方法【Google Chrome / Microsoft Edge】「お気に入り」の登録・削除方法【Google Chrome / Microsoft Edge】について解説している記事です。削除方法も掲載しています。...
【パソコン選び】失敗しないための重要ポイント | 現役エンジニア&プログラミングスクール講師【パソコン選び】失敗しないための重要ポイントについての記事です。パソコンのタイプと購入時に検討すべき点・家電量販店で見かけるCPUの見方・購入者が必要とするメモリ容量・HDDとSSDについて・ディスプレイの種類・バッテリーの持ち時間や保証・Officeソフト・ウィルス対策ソフトについて書いています。...
RELATED POST
11-Flask

Flask(Part.22予定)| 【複数アプリケーションの統合(2)】

2025年3月15日
プログラミング学習 おすすめ書籍情報発信 パソコン初心者 エンジニア希望者 新人エンジニア IT業界への就職・転職希望者 サポートサイト Programming learning Recommended schools Recommended books Information dissemination Computer beginners Prospective engineers New engineers Prospective job seekers in the IT industry Support site
11-Flask

Flask(Part.24)| 【テーブル管理アプリケーションのコミット】

2025年3月17日
プログラミング学習 おすすめ書籍情報発信 パソコン初心者 エンジニア希望者 新人エンジニア IT業界への就職・転職希望者 サポートサイト Programming learning Recommended schools Recommended books Information dissemination Computer beginners Prospective engineers New engineers Prospective job seekers in the IT industry Support site
11-Flask

Flask(Part.34)| 【注文管理アプリケーションのプログラミング(8)l(7)の解説】

2025年3月27日
プログラミング学習 おすすめ書籍情報発信 パソコン初心者 エンジニア希望者 新人エンジニア IT業界への就職・転職希望者 サポートサイト Programming learning Recommended schools Recommended books Information dissemination Computer beginners Prospective engineers New engineers Prospective job seekers in the IT industry Support site
11-Flask

Flask(Part.30)| 【注文管理アプリケーションのプログラミング(6)l(5)の解説】

2025年3月23日
プログラミング学習 おすすめ書籍情報発信 パソコン初心者 エンジニア希望者 新人エンジニア IT業界への就職・転職希望者 サポートサイト Programming learning Recommended schools Recommended books Information dissemination Computer beginners Prospective engineers New engineers Prospective job seekers in the IT industry Support site
11-Flask

Flask(Part.19)| 【画像のアップロードと利用(解説編)】

2025年3月12日
プログラミング学習 おすすめ書籍情報発信 パソコン初心者 エンジニア希望者 新人エンジニア IT業界への就職・転職希望者 サポートサイト Programming learning Recommended schools Recommended books Information dissemination Computer beginners Prospective engineers New engineers Prospective job seekers in the IT industry Support site