
PythonでChatGPTと一緒に住所録を作ろう:機能追加 保存
前回まででJSONデータを取り込むことができるようになりました。
あとは、フィルター、新規追加、編集、削除、保存ができるように機能を追加していきます。
今回は、データの保存機能を追加します。
1.データの保存
データの保存機能を追加します。
ChatGPTに以下のプロンプトを送信してください。
「(前回までのコードを貼り付けて)住所録のコードです。
データを保存できるようにメソッドを作ってください。」
ChatGPTの作ってくれたコードは以下のとおりです。
def save_data_to_json(self):
data = []
for row in range(self.table.rowCount()):
entry = {
"姓": self.table.item(row, 0).text() if self.table.item(row, 0) else "",
"姓フリガナ": self.table.item(row, 1).text() if self.table.item(row, 1) else "",
"名": self.table.item(row, 2).text() if self.table.item(row, 2) else "",
"名フリガナ": self.table.item(row, 3).text() if self.table.item(row, 3) else "",
"郵便番号": self.table.item(row, 4).text() if self.table.item(row, 4) else "",
"住所": self.table.item(row, 5).text() if self.table.item(row, 5) else "",
"電話番号": self.table.item(row, 6).text() if self.table.item(row, 6) else "",
"備考": self.table.item(row, 7).text() if self.table.item(row, 7) else ""
}
data.append(entry)
with open("address_book.json", "w", encoding="utf-8") as file:
json.dump(data, file, ensure_ascii=False, indent=4)
print("データを保存しました")
save_data_to_json() メソッドを、コードへ組み込みます。
クラスAddressBookApp の適当な場所にこのメソッドを追加します。
保存するファイル名 "address_book.json" を上書きしないように
"address_book_save.json" などの様に名前を変えておきます。
もう、一か所
self.save_button.clicked.connect(self.save_data_to_json)
このコードを setup_ui() メソッドの最後に追加してください。
これで"保存"ボタンをしたときに save_data_to_json() メソッドが実行されます。
これで住所録を起動して保存ボタンを押してみましょう。
内容を確認してください。
うまく行ったでしょうか。
2.コード解説
A.save_data_to_json()
for row in range(self.table.rowCount()):
entry = {
"姓": self.table.item(row, 0).text() if self.table.item(row, 0) else "",
"姓フリガナ": self.table.item(row, 1).text() if self.table.item(row, 1) else "",
"名": self.table.item(row, 2).text() if self.table.item(row, 2) else "",
"名フリガナ": self.table.item(row, 3).text() if self.table.item(row, 3) else "",
"郵便番号": self.table.item(row, 4).text() if self.table.item(row, 4) else "",
"住所": self.table.item(row, 5).text() if self.table.item(row, 5) else "",
"電話番号": self.table.item(row, 6).text() if self.table.item(row, 6) else "",
"備考": self.table.item(row, 7).text() if self.table.item(row, 7) else ""
}
data.append(entry)
self.table.rowCount()
これは、テーブルの行数なので
行数分forループを繰り返します。
そのたびにentryという辞書が作られます。
内容は、列数分あります。
姓の部分を一行だけ説明します。
"姓": self.table.item(row, 0).text() if self.table.item(row, 0) else "",
この書き方は、三項演算子と言う書き方です。
ChatGPTで確認しておきましょう。
if self.table.item(row, 0):
self.table.item(row, 0).text()
else:
""
と同じ意味になります。
つまり、1列目に値があればその文字列を取得し、
なければ空文字を設定する。
という事になります。
同じ事を8列分繰り返して出来上がった辞書1項目分を
dataに追加して住所録のリストを作ります。
with open("address_book.json", "w", encoding="utf-8") as file:
json.dump(data, file, ensure_ascii=False, indent=4)
"address_book.json"をテキスト形式で開いて
dataリストをjson形式で書き出します。
json.dump()の内容をChatGPTで押さえておきましょう。
ensure_ascii=False とすると日本語でファイルに出力されます。
indent=4 は、字下げをスペース4個分にする設定です。
B.connect()
self.save_button.clicked.connect(self.save_data_to_json)
save_buttonをクリックしたときに
save_data_to_json() を実行します。
3.全コード
"address_book.json" をコードの頭の方へ
モジュール変数として定義しなおしました。
DATA_FILE = "address_book.json"
モジュール変数とグローバル変数の動作の違いをChatGPTで確認しましょう。
この辺がPythonは、ややこしいですね。
バグを生みやすい部分。
A.コード
import sys
import json
from PyQt6.QtWidgets import (
QApplication, QMainWindow, QVBoxLayout, QHBoxLayout, QLineEdit, QPushButton,
QTableWidget, QTableWidgetItem, QHeaderView, QWidget, QLabel, QDialog, QFormLayout
)
DATA_FILE = "address_book.json"
class EditDialog(QDialog):
def __init__(self, parent=None):
super().__init__(parent)
self.setWindowTitle("編集画面")
self.setGeometry(200, 200, 400, 300)
layout = QFormLayout()
self.last_name_input = QLineEdit()
self.first_name_input = QLineEdit()
self.last_name_kana_input = QLineEdit()
self.first_name_kana_input = QLineEdit()
self.postal_code_input = QLineEdit()
self.address_input = QLineEdit()
self.phone_number_input = QLineEdit()
self.notes_input = QLineEdit()
layout.addRow("姓", self.last_name_input)
layout.addRow("名", self.first_name_input)
layout.addRow("姓フリガナ", self.last_name_kana_input)
layout.addRow("名フリガナ", self.first_name_kana_input)
layout.addRow("郵便番号", self.postal_code_input)
layout.addRow("住所", self.address_input)
layout.addRow("電話番号", self.phone_number_input)
layout.addRow("備考", self.notes_input)
self.save_button = QPushButton("保存")
self.cancel_button = QPushButton("キャンセル")
button_layout = QHBoxLayout()
button_layout.addWidget(self.save_button)
button_layout.addWidget(self.cancel_button)
layout.addRow(button_layout)
self.setLayout(layout)
class AddressBookApp(QMainWindow):
def __init__(self):
super().__init__()
self.setWindowTitle("住所録")
self.setGeometry(100, 100, 800, 600)
# GUIを構築
self.setup_ui()
# データを読み込む
self.load_data_from_json(DATA_FILE)
def setup_ui(self):
"""GUIを構築するメソッド"""
# メインウィジェットとレイアウト
main_widget = QWidget()
self.setCentralWidget(main_widget)
main_layout = QVBoxLayout()
main_widget.setLayout(main_layout)
# フィルター入力と実行ボタン
filter_layout = QHBoxLayout()
self.filter_input = QLineEdit()
self.filter_input.setPlaceholderText("フィルターを入力")
self.filter_button = QPushButton("実行")
filter_layout.addWidget(self.filter_input)
filter_layout.addWidget(self.filter_button)
main_layout.addLayout(filter_layout)
# 一覧表
self.table = QTableWidget()
self.table.setColumnCount(8)
self.table.setHorizontalHeaderLabels([
"姓", "姓フリガナ", "名", "名フリガナ", "郵便番号", "住所", "電話番号", "備考"
])
self.table.horizontalHeader().setSectionResizeMode(QHeaderView.ResizeMode.Stretch)
main_layout.addWidget(self.table)
# ボタン群
button_layout = QHBoxLayout()
self.new_button = QPushButton("新規作成")
self.edit_button = QPushButton("編集")
self.delete_button = QPushButton("削除")
self.save_button = QPushButton("保存")
self.load_button = QPushButton("読み込み")
button_layout.addWidget(self.new_button)
button_layout.addWidget(self.edit_button)
button_layout.addWidget(self.delete_button)
button_layout.addWidget(self.save_button)
button_layout.addWidget(self.load_button)
main_layout.addLayout(button_layout)
# ボタンの動作設定
self.new_button.clicked.connect(self.open_edit_dialog)
self.edit_button.clicked.connect(self.open_edit_dialog)
self.save_button.clicked.connect(self.save_data_to_json)
def load_data_from_json(self, file_path):
try:
# JSONデータの読み込み
with open(file_path, "r", encoding="utf-8") as file:
address_book = json.load(file)
# データをテーブルに追加
self.table.setRowCount(len(address_book)) # 行数を設定
for row, entry in enumerate(address_book):
for col, item in enumerate(["姓", "姓フリガナ", "名", "名フリガナ",
"郵便番号","住所", "電話番号", "備考"]):
cell = QTableWidgetItem(entry.get(item, ""))
self.table.setItem(row, col, cell)
except FileNotFoundError:
print("ファイルが見つかりません。")
except json.JSONDecodeError:
print("JSONデータが壊れています")
def save_data_to_json(self):
data = []
for row in range(self.table.rowCount()):
entry = {
"姓": self.table.item(row, 0).text() if self.table.item(row, 0) else "",
"姓フリガナ": self.table.item(row, 1).text() if self.table.item(row, 1) else "",
"名": self.table.item(row, 2).text() if self.table.item(row, 2) else "",
"名フリガナ": self.table.item(row, 3).text() if self.table.item(row, 3) else "",
"郵便番号": self.table.item(row, 4).text() if self.table.item(row, 4) else "",
"住所": self.table.item(row, 5).text() if self.table.item(row, 5) else "",
"電話番号": self.table.item(row, 6).text() if self.table.item(row, 6) else "",
"備考": self.table.item(row, 7).text() if self.table.item(row, 7) else ""
}
data.append(entry)
with open("address_book.json", "w", encoding="utf-8") as file:
json.dump(data, file, ensure_ascii=False, indent=4)
print("データを保存しました")
def open_edit_dialog(self):
dialog = EditDialog(self)
dialog.exec()
if __name__ == "__main__":
app = QApplication(sys.argv)
window = AddressBookApp()
window.show()
sys.exit(app.exec())
まとめ
ここまでで、データの保存ができる様になりました。
次回は、"新規作成"でデータを追加できる様にします。
お楽しみに。