wararajaz
@wararajaz

Are you sure you want to delete the question?

If your question is resolved, you may close it.

Leaving a resolved question undeleted may help others!

We hope you find it useful!

Pythonを用いたデータベースアプリの設計に関する質問

解決したいこと

ChatGPTを用いて音楽データベースを作ろうとしていたところ,データベースに設定した「リズム」「お気に入り」の二つの項目について,入力内容が逆転してしまうバグが起こっています.解決法をご教授いてだければと思います.

発生している問題・エラー

エラー表示なし.

![スクリーンショット 2024-11-12 14.30.26.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3933389/2b9cc756-4831-7c82-46f4-98a80b905ccd.png)
![スクリーンショット 2024-11-12 14.30.39.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3933389/92de34b0-3e4a-427a-5893-f504ce1cffa9.png)

該当するソースコード


import sqlite3
import tkinter as tk
from tkinter import messagebox, Toplevel, ttk

# データベースのセットアップ
conn = sqlite3.connect('music_database.db')
cursor = conn.cursor()

# テーブル作成(存在しない場合のみ作成)
cursor.execute('''
CREATE TABLE IF NOT EXISTS songs (
    id INTEGER PRIMARY KEY,
    title TEXT NOT NULL,
    artist TEXT,
    album TEXT,
    genre TEXT,
    release_year INTEGER,
    duration TEXT,
    authenticity INTEGER,
    realism INTEGER,
    originality INTEGER,
    lyrics INTEGER,
    melody INTEGER,
    tone INTEGER,
    rhythm INTEGER,
    favorite BOOLEAN
)
''')
conn.commit()

# Tkinterウィンドウのセットアップ
root = tk.Tk()
root.title("Music Database Entry")

# フォームのエントリーとラベル
tk.Label(root, text="曲名").grid(row=0, column=0)
title_entry = tk.Entry(root)
title_entry.grid(row=0, column=1)

tk.Label(root, text="アーティスト名").grid(row=1, column=0)
artist_entry = tk.Entry(root)
artist_entry.grid(row=1, column=1)

tk.Label(root, text="アルバム名").grid(row=2, column=0)
album_entry = tk.Entry(root)
album_entry.grid(row=2, column=1)

tk.Label(root, text="ジャンル").grid(row=3, column=0)
genre_entry = tk.Entry(root)
genre_entry.grid(row=3, column=1)

tk.Label(root, text="リリース年").grid(row=4, column=0)
release_year_entry = tk.Entry(root)
release_year_entry.grid(row=4, column=1)

tk.Label(root, text="再生時間").grid(row=5, column=0)
duration_entry = tk.Entry(root)
duration_entry.grid(row=5, column=1)

# 8項目の評価スライダー
criteria = [
    ("本物らしさ", "authenticity"),
    ("リアリズム", "realism"),
    ("斬新さ", "originality"),
    ("歌詞", "lyrics"),
    ("メロディ", "melody"),
    ("音色", "tone"),
    ("リズム", "rhythm")
]

sliders = {}
for i, (label_text, key) in enumerate(criteria, start=6):
    tk.Label(root, text=f"{label_text}(1-10)").grid(row=i, column=0)
    slider = tk.Scale(root, from_=1, to=10, orient="horizontal")
    slider.grid(row=i, column=1)
    sliders[key] = slider

# お気に入りフラグ
favorite_var = tk.BooleanVar()
favorite_checkbox = tk.Checkbutton(root, text="お気に入り", variable=favorite_var)
favorite_checkbox.grid(row=len(criteria) + 6, column=1)

# データベースに情報を保存する関数
# データベースに情報を保存する関数
def save_data():
    try:
        title = title_entry.get()
        artist = artist_entry.get()
        album = album_entry.get()
        genre = genre_entry.get()
        release_year = release_year_entry.get()
        duration = duration_entry.get()
        ratings = {key: slider.get() for key, slider in sliders.items()}
        favorite = favorite_var.get()

        if title:  # 曲名が入力されているかをチェック
            cursor.execute('''
            INSERT INTO songs (title, artist, album, genre, release_year, duration,
                               authenticity, realism, originality, lyrics, melody, tone, rhythm, favorite)
            VALUES (?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?)
            ''', (title, artist, album, genre, release_year, duration,
                  ratings["authenticity"], ratings["realism"], ratings["originality"],
                  ratings["lyrics"], ratings["melody"], ratings["tone"], ratings["rhythm"], favorite))
            conn.commit()
            messagebox.showinfo("Success", "データが保存されました")
        else:
            messagebox.showwarning("Error", "曲名を入力してください")
    except sqlite3.Error as e:
        messagebox.showerror("Database Error", f"データベースエラー: {e}")
    except Exception as e:
        messagebox.showerror("Unknown Error", f"予期しないエラー: {e}")

# 保存ボタン
save_button = tk.Button(root, text="保存", command=save_data)
save_button.grid(row=len(criteria) + 7, column=1)

# 一覧表示のウィンドウを開く関数
def show_data():
    # 別ウィンドウを作成
    list_window = Toplevel(root)
    list_window.title("保存されたデータ一覧")
    
    # Treeviewウィジェットでテーブル形式でデータを表示
    tree = ttk.Treeview(list_window, columns=("ID", "曲名", "アーティスト", "アルバム", "ジャンル", "リリース年",
                                              "再生時間", "本物らしさ", "リアリズム", "斬新さ", "歌詞", "メロディ", "音色", "リズム", "お気に入り"),
                        show="headings")
    
    # 各列のヘッダーを設定(横幅を狭く設定)
    column_widths = [30, 100, 80, 80, 60, 60, 60, 40, 40, 40, 40, 40, 40, 40, 60]
    for col, width in zip(tree["columns"], column_widths):
        tree.heading(col, text=col)
        tree.column(col, width=width)
    
    tree.pack(fill="both", expand=True)

    # データベースからデータを取得して挿入
    cursor.execute("SELECT * FROM songs")
    rows = cursor.fetchall()
    for row in rows:
        tree.insert("", "end", values=row)

    # 選択されたデータを削除する関数
    def delete_selected():
        selected_item = tree.selection()
        if selected_item:
            item = tree.item(selected_item)
            song_id = item["values"][0]  # IDを取得
            cursor.execute("DELETE FROM songs WHERE id=?", (song_id,))
            conn.commit()
            tree.delete(selected_item)  # 表示からも削除
            messagebox.showinfo("Success", "データが削除されました")
        else:
            messagebox.showwarning("Error", "削除する項目を選択してください")

    # 削除ボタン
    delete_button = tk.Button(list_window, text="削除", command=delete_selected)
    delete_button.pack()

# 一覧表示ボタン
view_button = tk.Button(root, text="一覧表示", command=show_data)
view_button.grid(row=len(criteria) + 8, column=1)

# GUIのメインループ
root.mainloop()

# ウィンドウを閉じる際にデータベースを閉じる
conn.close()


自分で試したこと

INSERT INTOの中身の順番の確認は行ったが,正しい順番でも正常に機能しない.

0

2Answer

まずDBにどのように登録されているのか確認してみてはいかがでしょうか

  • 入力項目には、どの項目がわかるように全部いれてください。例えばアーティスト項目には、アーティストなどと入力してください
  • スライダーの値は、1,2,3,・・・と階段状にして、入力値で項目が区別できるようにしてください

sqliteは次の記事によると、次のようにしたらdbに登録した値が確認できそうです。

コンソールで、
sqlite3 music_database.db
SELECT * FROM songs ;
抜けるには
.exit
selectで全件表示するはずなので、登録されたデータが、考えている形で登録されているか確認できると思います。

1Like

Comments

  1. @wararajaz

    Questioner

    ご回答ありがとうございます.教えていただいたようにデータベースに登録後,確認して見たところ,一覧表示と同様にrhithmとfavoriteの値が逆転して保存されてしまっており,それ以外は正常に登録できていることが確認されました.

    スクリーンショット 2024-11-13 16.33.12.png

  2. @wararajaz

    Questioner

    他に試したこととしては,コードからfavoriteに関する項目を無効化して動かして見たところ,rhythmの登録データがNoneと表示されました.

    スクリーンショット 2024-11-13 16.49.43.png

  3. @wararajaz

    Questioner

    連投になってしまい申し訳ありません.save_dataの中のINSERTを行う直前で

    print("Saving data:", (title, artist, album, genre, release_year, duration,
    ratings["authenticity"], ratings["realism"], ratings["originality"],
    ratings["lyrics"], ratings["melody"], ratings["tone"], ratings["rhythm"], favorite))

    以上を入れて確認してみると,以下のように表示されました.(曲名以外の文字データの登録は省いています)

    スクリーンショット 2024-11-13 17.02.36.png

  4. 確認ありがとうございます。
    DBの登録時点で変になっている、ということが確認出来てよかったです。
    (データ取り出し時から、画面表示のところで変になっているのかも?と疑ってました)

    DBに登録する前に、

    print(title, artist, album, genre, release_year, duration,
                      ratings["authenticity"], ratings["realism"], ratings["originality"],
                      ratings["lyrics"], ratings["melody"], ratings["tone"], ratings["rhythm"], favorite)
    

    ってしたら、どのようになりますか?

    最初に確認してもらったように、画面から全部の内容を入力して、どのように表示されるか見てみたいです。

    根拠なく見た感じの直感では、次のあたりがなんとなくあやしいかな?と予想しています。

    for i, (label_text, key) in enumerate(criteria, start=6):
    
    favorite_checkbox.grid(row=len(criteria) + 6, column=1)
    

画像を貼付しようとしていますか?アップロードできていませんのでご確認ください。

1Like

Comments

  1. コードブロックのせいで画像として表示されていないだけのようで、アドレスに移動すると表示されました。
    参考までに問い合わせ内容のコピペで表示させてみます。

    スクリーンショット 2024-11-12 14.30.26.png
    スクリーンショット 2024-11-12 14.30.39.png

  2. favoriteはboolになってますが、rhythmが増加したときもbool(つまり0か1)になってる感じですか?
    そうじゃないなら、逆転してるように見えるだけで別のバグかも。

  3. @wararajaz

    Questioner

    画像のご指摘と補足ありがとうございます.
    favoriteはboolをとるようにしているつもりですが,データには1-10の数値で登録されてしまっています.rhythmは「お気に入り」のチェックの有無に応じて0-1で登録されてしまいます.
    データ入力か保存の箇所にバグがあるのではと今のところ考えているのですが,私一人では思い当たる箇所がないという状況です...

Your answer might help someone💌