回答編集履歴

14

追記

2023/10/01 02:54

投稿

退会済みユーザー
test CHANGED
@@ -294,10 +294,8 @@
294
294
 
295
295
  # 追記
296
296
  あまり最初から詰め込みすぎると混乱の原因となるため、ここでは詳細は書きませんが、上記のコードではエラーではないものの、まだ以下の問題点があります。
297
- + main.pyの@app.route('/')で、booksリストにインデックスを使ってデータを渡している
297
+ + main.pyの@app.route('/')で、booksリストにインデックスを使ってデータを渡している→この結果、何か修正の必要が生じた場合に、データベースに格納されているデータのカラムの順番を意識しないといけない
298
- + データベースのカラムを追加/削除し場合、カラムの順番を意識して書き換る必要がある。(上記だと、idというカラムを先頭に追加したため、delete.html の表示インデックスを1つずらしている)
298
+ 上記だと、idというカラムを先頭に追加したため、delete.html の表示インデックスを1つずらしている)
299
-
300
- →この結果、何か修正の必要が生じた場合に、データベースに格納されているデータのカラムの順番を意識しないといけない
299
+
301
-
302
- のような問題対処することを考えると、データベースからデータを取得する際は、row_factory を使用した方がベターです。興味があれば調べてみるのもよいでしょう。
300
+ ついては、データベースからデータを取得する際row_factory を使用することで少メンテしやくなります。興味があれば調べてみるのもよいでしょう。
303
-
301
+

13

追記

2023/10/01 02:43

投稿

退会済みユーザー
test CHANGED
@@ -290,3 +290,14 @@
290
290
  上記修正内容を試す場合は、修正後初回のみ、一旦 flask を終了し、プロジェクト内の database.db ファイルを削除してから run.py を再実行するようにしてください。
291
291
  修正前のdatabase.dbが残っている状態で起動した場合、うまく動作しません。
292
292
 
293
+ ---
294
+
295
+ # 追記
296
+ あまり最初から詰め込みすぎると混乱の原因となるため、ここでは詳細は書きませんが、上記のコードではエラーではないものの、まだ以下の問題点があります。
297
+ + main.pyの@app.route('/')で、booksリストにインデックスを使ってデータを渡している。
298
+ + データベースのカラムを追加/削除した場合、カラムの順番を意識して書き換える必要がある。(上記だと、idというカラムを先頭に追加したため、delete.html の表示インデックスを1つずらしている)
299
+
300
+ →この結果、何か修正の必要が生じた場合に、データベースに格納されているデータのカラムの順番を意識しないといけない
301
+
302
+ このような問題に対処することを考えると、データベースからデータを取得する際は、row_factory を使用した方がベターです。興味があれば調べてみるのもよいでしょう。
303
+

12

a

2023/10/01 01:41

投稿

退会済みユーザー
test CHANGED
@@ -89,7 +89,7 @@
89
89
 
90
90
  ## main.py の修正
91
91
  ### root ('/') の修正
92
- root ('/') では、db_booksに、データベースから取得した id も渡すように修正します。
92
+ root ('/') では、index.html の books に、データベースから取得した id も渡すように修正します。
93
93
  ```main.py
94
94
  books.append({"title": row[0], "price": row[1], "arrival_day": row[2]})
95
95
          ↓

11

2023/10/01 01:22

投稿

退会済みユーザー
test CHANGED
@@ -11,9 +11,9 @@
11
11
  ```
12
12
  book = con.execute('SELECT * FROM books WHERE id = ?', [id]).fetchone()
13
13
  ```
14
- と言う部分でエラーが発生しているということが分かります。
14
+ と言う部分で「sqlite3.OperationalError: no such column: id 」というエラーが発生しているということが分かります。
15
-
15
+
16
- このエラーの原因は、データベースに「id」というカラムが存在していないためす。
16
+ このエラーは、データベースに「id」というカラムが存在していないために発生しています。
17
17
  したがって、データベースに「id」というカラムが存在している必要があります。
18
18
  以下、データベースに「id」カラムを作成し、id で書籍を管理するように作り変えます。
19
19
 

10

e

2023/10/01 00:35

投稿

退会済みユーザー
test CHANGED
@@ -1,5 +1,5 @@
1
1
  ## エラーの原因
2
- エラーの最後から~8行目(空白行除く)を読むと
2
+ エラーの最後から 6~8行目(空白行除く)を読むと
3
3
  ```
4
4
  File "/Users/kojitakemura/Desktop/pythonProject1 2元本 2/flaskr/main.py", line 58, in delete
5
5
  book = con.execute('SELECT * FROM books WHERE id = ?', [id]).fetchone()
@@ -7,11 +7,21 @@
7
7
  ```
8
8
  と書いてあります。
9
9
 
10
+ このエラーメッセージから、main.py 58 行目の
11
+ ```
12
+ book = con.execute('SELECT * FROM books WHERE id = ?', [id]).fetchone()
13
+ ```
14
+ と言う部分でエラーが発生しているということが分かります。
15
+
10
16
  このエラーの原因は、データベースに「id」というカラムが存在していないためです。
11
- なので、データベースに「id」というカラムが存在している必要があります。
17
+ したがって、データベースに「id」というカラムが存在している必要があります。
12
- 以下データベースに「id」カラムを作成し、id で書籍を管理するように作り変えます。
18
+ 以下データベースに「id」カラムを作成し、id で書籍を管理するように作り変えます。
19
+
13
-
20
+ ---
21
+  
22
+ # データベースに「id」カラムを作成し、id で書籍を管理するように作り変えるための修正
23
+
14
- # db.pyの修正
24
+ ## db.pyの修正
15
25
  db.py では、database.db 内に books という名前のテーブルが存在するか判定し、存在しない場合は books テーブルを新規作成しています。
16
26
  このとき、books テーブル内に id カラムも作成するように修正します。
17
27
 

9

e

2023/10/01 00:29

投稿

退会済みユーザー
test CHANGED
@@ -94,7 +94,7 @@
94
94
  con.execute('INSERT INTO books (title, price, arrival_day) VALUES(?, ?, ?)',[title, price, arrival_day])
95
95
  ```
96
96
  ## その他
97
- form.html の後半なぜかdelete.html の内容が重複しています。文法的にも誤っていると思われるため、特別な目的がない限り、後半は削除した方が良いでしょう。
97
+ form.html の後半なぜかdelete.html の内容が重複しています。特別な目的がない限り、後半は削除した方が良いでしょう。
98
98
 
99
99
 
100
100
  ---

8

修正

2023/10/01 00:25

投稿

退会済みユーザー
test CHANGED
@@ -80,15 +80,17 @@
80
80
  ## main.py の修正
81
81
  ### root ('/') の修正
82
82
  root ('/') では、db_booksに、データベースから取得した id も渡すように修正します。
83
- ```py
83
+ ```main.py
84
+ books.append({"title": row[0], "price": row[1], "arrival_day": row[2]})
85
+         ↓
84
86
  books.append({"id": row[0], "title": row[1], "price": row[2], "arrival_day": row[3]})
85
87
  ```
86
88
  ## /register の修正
87
89
  id を 自動付番に変えた関係上、/register のSQL文はそのままだとエラーになります。
88
90
  ここでは、データベースに追加するレコードのカラム名を明示的に指定するよう修正します。
89
- ```py
91
+ ```main.py
90
92
  con.execute('INSERT INTO books VALUES(?,?,?)',[title,price,arrival_day])
91
-   ↓
93
+     
92
94
  con.execute('INSERT INTO books (title, price, arrival_day) VALUES(?, ?, ?)',[title, price, arrival_day])
93
95
  ```
94
96
  ## その他
@@ -98,7 +100,7 @@
98
100
  ---
99
101
 
100
102
  # 修正後全体
101
- 修正後の各コードは以下す。
103
+ 修正した各コード全体は以下のようになりす。
102
104
  ```main.py
103
105
  from crypt import methods
104
106
  from turtle import title

7

e

2023/10/01 00:21

投稿

退会済みユーザー
test CHANGED
@@ -12,8 +12,8 @@
12
12
  以下データベースに「id」カラムを作成し、id で書籍を管理するように作り変えます。
13
13
 
14
14
  # db.pyの修正
15
- db.py では、プロジェクト内にテーブル(database.dbが存在するか判定し、存在しない場合はテーブルを作成しています。
15
+ db.py では、database.db 内に books という名前のテーブルが存在するか判定し、存在しない場合は books テーブルを新規作成しています。
16
- このとき、テーブル内に id カラムも作成するようにします。
16
+ このとき、books テーブル内に id カラムも作成するように修正します。
17
17
 
18
18
  ```db.py
19
19
  import sqlite3
@@ -26,7 +26,7 @@
26
26
  con.close()
27
27
  ```
28
28
 
29
- CERATE文のところ「**id INTEGER PRIMARY KEY AUTOINCREMENT**」を追加しています。
29
+ CERATE文のところ「**id INTEGER PRIMARY KEY AUTOINCREMENT**」を追加しています。
30
30
  これは
31
31
  + 「id」と言う名前のカラムを作成
32
32
  + id の型(整数)、主キー制約(PRIMARY KEY)、自動付番(AUTOINCREMENT)を設定

6

2023/10/01 00:20

投稿

退会済みユーザー
test CHANGED
@@ -66,7 +66,7 @@
66
66
 
67
67
 
68
68
  ## delete.html の修正
69
- delete.html もIDを表示するように修正します。(これも必須ではありませんが、動作をわかりやすくするためです)
69
+ データベースの構造を変更したのに合わせて、delete.html も修正します。
70
70
  ```delete.html
71
71
  ...略...
72
72
 

5

2023/10/01 00:18

投稿

退会済みユーザー
test CHANGED
@@ -65,7 +65,7 @@
65
65
  ```
66
66
 
67
67
 
68
- # delete.html の修正
68
+ ## delete.html の修正
69
69
  delete.html もIDを表示するように修正します。(これも必須ではありませんが、動作をわかりやすくするためです)
70
70
  ```delete.html
71
71
  ...略...
@@ -91,6 +91,11 @@
91
91
    ↓
92
92
  con.execute('INSERT INTO books (title, price, arrival_day) VALUES(?, ?, ?)',[title, price, arrival_day])
93
93
  ```
94
+ ## その他
95
+ form.html の後半に なぜかdelete.html の内容が重複しています。文法的にも誤っていると思われるため、特別な目的がない限り、後半は削除した方が良いでしょう。
96
+
97
+
98
+ ---
94
99
 
95
100
  # 修正後全体
96
101
  修正後の各コードは以下です。

4

修正

2023/10/01 00:14

投稿

退会済みユーザー
test CHANGED
@@ -1,5 +1,5 @@
1
- # エラーの原因
1
+ ## エラーの原因
2
- エラーの最後から7~8行目(空白行く)を読むと
2
+ エラーの最後から7~8行目(空白行く)を読むと
3
3
  ```
4
4
  File "/Users/kojitakemura/Desktop/pythonProject1 2元本 2/flaskr/main.py", line 58, in delete
5
5
  book = con.execute('SELECT * FROM books WHERE id = ?', [id]).fetchone()
@@ -7,12 +7,14 @@
7
7
  ```
8
8
  と書いてあります。
9
9
 
10
- このエラーの原因は、実際のデータベースに「id」というカラムが存在していないためです。
10
+ このエラーの原因は、データベースに「id」というカラムが存在していないためです。
11
- なので、データベースに「id」というカラムがなければせん
11
+ なので、データベースに「id」というカラムが存在してる必要があり
12
- 以下データベースに「id」カラムを作成し、idで書籍を管理するように作り変えます。
12
+ 以下データベースに「id」カラムを作成し、id で書籍を管理するように作り変えます。
13
-
13
+
14
- # データベース作成時設定
14
+ # db.py修正
15
+ db.py では、プロジェクト内にテーブル(database.db)が存在するか判定し、存在しない場合はテーブルを作成しています。
15
- 一番最初、テーブルを作るときidってあげます。
16
+ このとき、テーブル id カラムも成するようにします。
17
+
16
18
  ```db.py
17
19
  import sqlite3
18
20
 
@@ -31,11 +33,12 @@
31
33
  の意味です。
32
34
 
33
35
  2番目のように設定する理由はidの重複を防ぐためです。仮にidの重複を許してしまうと、削除する時に書籍を区別できず、指定した書籍と別の書籍を削除してしまう可能性があります。
34
-
36
+  
37
+
35
- # index.html の修正
38
+ ## index.html の修正
36
39
  index.html を下記のように修正します。
37
- + idを表示する列を追加
40
+ + データベースの id カラムを表示する列を追加(必須ではありませんが動作をわかりやすくするため)
38
- + 削除リンククリック時、idをdelete.htmlに渡すよう変更
41
+ + 削除リンクに、コントローラ(main.py)から受け取った id をつける → このようにすることで、削除リンリック時に書籍ID delete.html に渡すことが可能なります。
39
42
  ```index.html
40
43
  ...略...
41
44
  <table border="1">
@@ -63,7 +66,7 @@
63
66
 
64
67
 
65
68
  # delete.html の修正
66
- delete.html もIDを表示するように修正します。
69
+ delete.html もIDを表示するように修正します。(これも必須ではありませんが、動作をわかりやすくするためです)
67
70
  ```delete.html
68
71
  ...略...
69
72
 
@@ -74,21 +77,23 @@
74
77
  ...略...
75
78
  ```
76
79
 
77
- # main.py の修正
80
+ ## main.py の修正
78
- ## root ('/') の修正
81
+ ### root ('/') の修正
79
- root ('/') では下記のように修正します。
82
+ root ('/') では、db_booksに、データベースから取得した id も渡すように修正します。
80
- + db_booksに、idも一緒に渡すようにする。
81
83
  ```py
82
84
  books.append({"id": row[0], "title": row[1], "price": row[2], "arrival_day": row[3]})
83
85
  ```
84
86
  ## /register の修正
85
- /register のSQL文で、id を 自動付番に変えた関係上、そのままだとエラーになるので、渡す変数を明示する必要があります。
87
+ id を 自動付番に変えた関係上、/register のSQL文はそのままだとエラーになります。
88
+ ここでは、データベースに追加するレコードのカラム名を明示的に指定するよう修正します。
86
89
  ```py
90
+ con.execute('INSERT INTO books VALUES(?,?,?)',[title,price,arrival_day])
91
+   ↓
87
92
  con.execute('INSERT INTO books (title, price, arrival_day) VALUES(?, ?, ?)',[title, price, arrival_day])
88
93
  ```
89
94
 
90
- # main.py 修正後全体
95
+ # 修正後全体
91
- main.py全体の修正後のコードは以下です。
96
+ 修正後のコードは以下です。
92
97
  ```main.py
93
98
  from crypt import methods
94
99
  from turtle import title
@@ -133,9 +138,6 @@
133
138
  con.commit()
134
139
  con.close()
135
140
  return redirect(url_for("index"))
136
-
137
-
138
-
139
141
 
140
142
  @app.route('/delete/<int:id>', methods=['GET', 'POST'])
141
143
  def delete(id):
@@ -154,6 +156,120 @@
154
156
  return "Book not found", 404
155
157
  ```
156
158
 
159
+ ```db.py
160
+ import sqlite3
161
+
162
+
163
+ DATABASE = "database.db"
164
+
165
+ def create_books_table():
166
+ con = sqlite3.connect(DATABASE)
167
+ con.execute("CREATE TABLE IF NOT EXISTS books (id INTEGER PRIMARY KEY AUTOINCREMENT, title, price, arrival_day)")
168
+ con.close()
169
+ ```
170
+
171
+ ```index.html
172
+ <!DOCTYPE html>
173
+ <html lang="ja">
174
+
175
+ <head>
176
+ <meta charset="UTF-8">
177
+ <title>sapu-app</title>
178
+
179
+ <link rel="stylesheet" href="{{ url_for('static', filename='style.css') }}">
180
+ </head>
181
+
182
+ <body>
183
+
184
+ <h1>書店</h1>
185
+ <h2>今月の新刊一覧</h2>
186
+ {% if books == [] %}
187
+ <p>今月の新刊情報はまだありません</p>
188
+ {% else %}
189
+ <table border="1">
190
+ <tr>
191
+ <th>ID</th>
192
+ <th>入荷日</th>
193
+ <th>タイトル</th>
194
+ <th>金額</th>
195
+ <th>削除</th>
196
+ </tr>
197
+
198
+ {% for book in books %}
199
+ <tr>
200
+ <td>{{ book.id }}</td>
201
+ <td>{{ book.arrival_day }}</td>
202
+ <td>{{ book.title }}</td>
203
+ <td>{{ book.price }}円</td>
204
+ <td>
205
+ <a href="{{ url_for('delete', id=book.id) }}">Delete</a>
206
+ </td>
207
+ </tr>
208
+ {% endfor %}
209
+ </table>
210
+ {% endif %}
211
+
212
+ <a href= "{{ url_for('form') }}">編集</a>
213
+ </body>
214
+ </html>
215
+ ```
216
+
217
+ ```delete.html
218
+ <!DOCTYPE html>
219
+ <html lang="jp">
220
+ <head>
221
+ <meta charset="UTF-8">
222
+ <title>Delete Book</title>
223
+ </head>
224
+ <body>
225
+ <h1>Delete Book</h1>
226
+ <p>Are you sure you want to delete the following book?</p>
227
+ <p>ID : {{ book[0] }}</p>
228
+ <p>Title: {{ book[1] }}</p>
229
+ <p>Price: {{ book[2] }}</p>
230
+ <p>Arrival Day: {{ book[3] }}</p>
231
+ <form method="POST">
232
+ <input type="submit" value="Delete">
233
+ </form>
234
+ </body>
235
+ </html>
236
+ ```
237
+
238
+ ```form.html
239
+ <!DOCTYPE html>
240
+ <html lang="ja">
241
+
242
+ <head>
243
+ <meta charset="UTF-8">
244
+ <title>sapu-app</title>
245
+
246
+ <link rel="stylesheet" href="{{ url_for('static', filename='style.css') }}">
247
+
248
+ </head>
249
+
250
+ <body>
251
+ <h1>書店</h1>
252
+ <form method="post" action="{{ url_for('register') }}">
253
+ <table border="1">
254
+ <tr>
255
+ <th>入荷日</th>
256
+ <th>タイトル</th>
257
+ <th>金額</th>
258
+ </tr>
259
+ <tr>
260
+ <td><input type="text" name="arrival_day"></td>
261
+ <td><input type="text" name="title"></td>
262
+ <td><input type="text" name="price"></td>
263
+ </tr>
264
+ </table>
265
+ <br>
266
+ <input type="submit" value="登録">
267
+ </form>
268
+ </body>
269
+ </html>
270
+ ```
271
+
272
+ # 注意
157
- 上記修正内容を試す場合は、一旦flaskを終了し、プロジェクト内のdatabase.dbファイルを削除してからrun.pyを再実行するようにしてください。
273
+ 上記修正内容を試す場合は、修正後初回のみ、一旦 flask を終了し、プロジェクト内の database.db ファイルを削除してから run.py を再実行するようにしてください。
158
- データベース構造自体を変える必要があるため、元のdatabase.dbが残っている状態で起動した場合、うまく動作しません。
274
+ 修正前のdatabase.dbが残っている状態で起動した場合、うまく動作しません。
159
-
275
+

3

初回起動方法について追記

2023/09/30 23:55

投稿

退会済みユーザー
test CHANGED
@@ -154,3 +154,6 @@
154
154
  return "Book not found", 404
155
155
  ```
156
156
 
157
+ 上記修正内容を試す場合は、一旦flaskを終了し、プロジェクト内のdatabase.dbファイルを削除してからrun.pyを再実行するようにしてください。
158
+ データベースの構造自体を変える必要があるため、元のdatabase.dbが残っている状態で起動した場合、うまく動作しません。
159
+

2

修正

2023/09/30 23:52

投稿

退会済みユーザー
test CHANGED
@@ -13,10 +13,8 @@
13
13
 
14
14
  # データベース作成時の設定
15
15
  一番最初、テーブルを作るときに、idを作ってあげます。
16
- db.py
16
+ ```db.py
17
- ```py
18
17
  import sqlite3
19
-
20
18
 
21
19
  DATABASE = "database.db"
22
20
 
@@ -38,7 +36,8 @@
38
36
  index.html を下記のように修正します。
39
37
  + idを表示する列を追加
40
38
  + 削除リンククリック時、idをdelete.htmlに渡すように変更
41
- ```html
39
+ ```index.html
40
+ ...略...
42
41
  <table border="1">
43
42
  <tr>
44
43
  <th>ID</th>
@@ -59,16 +58,20 @@
59
58
  </td>
60
59
  </tr>
61
60
  {% endfor %}
61
+ ...略...
62
62
  ```
63
63
 
64
64
 
65
65
  # delete.html の修正
66
66
  delete.html もIDを表示するように修正します。
67
- ```html
67
+ ```delete.html
68
+ ...略...
69
+
68
70
  <p>ID : {{ book[0] }}</p>
69
71
  <p>Title: {{ book[1] }}</p>
70
72
  <p>Price: {{ book[2] }}</p>
71
73
  <p>Arrival Day: {{ book[3] }}</p>
74
+ ...略...
72
75
  ```
73
76
 
74
77
  # main.py の修正
@@ -79,14 +82,14 @@
79
82
  books.append({"id": row[0], "title": row[1], "price": row[2], "arrival_day": row[3]})
80
83
  ```
81
84
  ## /register の修正
82
- + /register のSQL文で、id を 自動付番に変えた関係上、そのままだとエラーになるので、渡す変数を明示する必要があります。
85
+ /register のSQL文で、id を 自動付番に変えた関係上、そのままだとエラーになるので、渡す変数を明示する必要があります。
83
86
  ```py
84
87
  con.execute('INSERT INTO books (title, price, arrival_day) VALUES(?, ?, ?)',[title, price, arrival_day])
85
88
  ```
86
89
 
87
- # main.py 全体
90
+ # main.py 修正後全体
88
91
  main.py全体の修正後のコードは以下です。
89
- ```py
92
+ ```main.py
90
93
  from crypt import methods
91
94
  from turtle import title
92
95
  #db 追加
@@ -134,7 +137,6 @@
134
137
 
135
138
 
136
139
 
137
- #以下追記した削除コードです
138
140
  @app.route('/delete/<int:id>', methods=['GET', 'POST'])
139
141
  def delete(id):
140
142
  con = sqlite3.connect(DATABASE)

1

修正

2023/09/30 23:48

投稿

退会済みユーザー
test CHANGED
@@ -74,5 +74,81 @@
74
74
  # main.py の修正
75
75
  ## root ('/') の修正
76
76
  root ('/') では下記のように修正します。
77
+ + db_booksに、idも一緒に渡すようにする。
78
+ ```py
79
+ books.append({"id": row[0], "title": row[1], "price": row[2], "arrival_day": row[3]})
80
+ ```
81
+ ## /register の修正
82
+ + /register のSQL文で、id を 自動付番に変えた関係上、そのままだとエラーになるので、渡す変数を明示する必要があります。
83
+ ```py
84
+ con.execute('INSERT INTO books (title, price, arrival_day) VALUES(?, ?, ?)',[title, price, arrival_day])
85
+ ```
86
+
87
+ # main.py 全体
88
+ main.py全体の修正後のコードは以下です。
89
+ ```py
90
+ from crypt import methods
91
+ from turtle import title
92
+ #db 追加
93
+ from flaskr import app, db
94
+ from flask import render_template, request, redirect, url_for
95
+
96
+ from flaskr.db import DATABASE
97
+
98
+ import sqlite3
99
+ DATABASE = "database.db"
100
+
101
+
102
+ @app.route('/')
103
+ def index():
104
+ con = sqlite3.connect(DATABASE)
105
+ db_books = con.execute("SELECT * FROM books").fetchall()
106
+ con.close
107
+
108
+
109
+ books = []
110
+ for row in db_books:
111
+ books.append({"id": row[0], "title": row[1], "price": row[2], "arrival_day": row[3]})
112
+
113
+ return render_template(
114
+ 'index.html',books=books
77
- +
115
+ )
116
+
117
+ @app.route("/form")
118
+ def form():
119
+ return render_template("form.html")
120
+
121
+ @app.route("/register", methods=["POST"])
122
+ def register():
123
+ title = request.form["title"]
124
+ price = request.form["price"]
125
+ arrival_day =request.form["arrival_day"]
126
+
127
+ con = sqlite3.connect(DATABASE)
128
+ con.execute('INSERT INTO books (title, price, arrival_day) VALUES(?, ?, ?)',[title, price, arrival_day])
129
+
130
+ con.commit()
131
+ con.close()
132
+ return redirect(url_for("index"))
133
+
134
+
135
+
136
+
137
+ #以下追記した削除コードです
138
+ @app.route('/delete/<int:id>', methods=['GET', 'POST'])
139
+ def delete(id):
140
+ con = sqlite3.connect(DATABASE)
141
+ if request.method == 'POST':
142
+ con.execute('DELETE FROM books WHERE id = ?', [id])
143
+ con.commit()
144
+ con.close()
145
+ return redirect(url_for('index'))
146
+ else:
147
+ book = con.execute('SELECT * FROM books WHERE id = ?', [id]).fetchone()
148
+ con.close()
149
+ if book:
150
+ return render_template('delete.html', book=book)
151
+ else:
152
+ return "Book not found", 404
78
- +
153
+ ```
154
+