cwadayi commited on
Commit
8198489
·
verified ·
1 Parent(s): 02ebf53

Update app.py

Browse files
Files changed (1) hide show
  1. app.py +122 -14
app.py CHANGED
@@ -1,70 +1,178 @@
1
  # app.py
2
 
3
  from fastapi import FastAPI, HTTPException
4
- from pydantic import BaseModel # <--- Import BaseModel
 
5
  import sqlite3
6
  import os
7
 
8
  # Define the Pydantic model for Item creation/update
9
  class Item(BaseModel):
10
  name: str
11
- description: str | None = None # Use Union type hint for None
 
 
 
 
 
 
12
 
13
  app = FastAPI()
14
 
15
- # ... rest of your existing code ...
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
16
 
17
  @app.post("/items/")
18
- async def create_item(item: Item): # <--- Change parameter to 'item: Item'
 
19
  conn = get_db_connection()
20
  cursor = conn.cursor()
21
  try:
22
  query = "INSERT INTO items (name, description) VALUES (?, ?)"
23
- cursor.execute(query, (item.name, item.description)) # Access attributes using item.name, item.description
24
  conn.commit()
25
  return {"message": "Item created successfully", "id": cursor.lastrowid}
26
  except Exception as e:
27
- conn.rollback()
28
  raise HTTPException(status_code=500, detail=f"Error creating item: {e}")
29
  finally:
30
  cursor.close()
31
  conn.close()
32
 
33
- # ... Also update your @app.put("/items/{item_id}") endpoint similarly ...
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
34
  @app.put("/items/{item_id}")
35
- async def update_item(item_id: int, item: Item): # <--- Change parameter to 'item: Item'
 
36
  conn = get_db_connection()
37
  cursor = conn.cursor()
38
  try:
39
  updates = []
40
  params = []
41
 
42
- if item.name is not None: # Access using item.name
43
  updates.append("name = ?")
44
  params.append(item.name)
45
- if item.description is not None: # Access using item.description
46
  updates.append("description = ?")
47
  params.append(item.description)
48
 
49
  if not updates:
 
50
  raise HTTPException(status_code=400, detail="No fields to update provided")
51
 
52
  query = f"UPDATE items SET {', '.join(updates)} WHERE id = ?"
53
- params.append(item_id)
54
 
55
  cursor.execute(query, tuple(params))
56
  conn.commit()
57
 
58
  if cursor.rowcount == 0:
 
59
  raise HTTPException(status_code=404, detail="Item not found")
60
  return {"message": "Item updated successfully"}
61
- except HTTPException: # Re-raise if it's already an HTTPException
62
  raise
63
  except Exception as e:
64
- conn.rollback()
65
  raise HTTPException(status_code=500, detail=f"Error updating item: {e}")
66
  finally:
67
  cursor.close()
68
  conn.close()
69
 
70
- # ... rest of your existing code ...
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
  # app.py
2
 
3
  from fastapi import FastAPI, HTTPException
4
+ from pydantic import BaseModel
5
+ from typing import Union # Correct import for Union type hints in Python < 3.10
6
  import sqlite3
7
  import os
8
 
9
  # Define the Pydantic model for Item creation/update
10
  class Item(BaseModel):
11
  name: str
12
+ description: Union[str, None] = None # Corrected syntax for Python 3.9
13
+
14
+ # Define the Pydantic model for Item update specifically (allowing partial updates)
15
+ # This model allows all fields to be optional, so you can update just 'name' or just 'description'
16
+ class ItemUpdate(BaseModel):
17
+ name: Union[str, None] = None
18
+ description: Union[str, None] = None
19
 
20
  app = FastAPI()
21
 
22
+ # Define the path for your SQLite database file
23
+ # This will be created in the /app directory of your Hugging Face Space.
24
+ # Files in /app are generally persisted across restarts within a Space.
25
+ DATABASE_FILE = os.path.join(os.getcwd(), "data.db")
26
+
27
+ def get_db_connection():
28
+ """Establishes and returns a SQLite database connection."""
29
+ try:
30
+ conn = sqlite3.connect(DATABASE_FILE)
31
+ # Configure connection to return rows as dictionaries for easier access
32
+ conn.row_factory = sqlite3.Row
33
+ return conn
34
+ except sqlite3.Error as err:
35
+ print(f"Error connecting to database: {err}")
36
+ # In a real-world scenario, you might want to log this error and potentially
37
+ # use a more sophisticated error handling strategy.
38
+ raise HTTPException(status_code=500, detail="Database connection error")
39
+
40
+ @app.on_event("startup")
41
+ async def startup_event():
42
+ """
43
+ Initializes the database: creates the 'items' table if it doesn't exist.
44
+ This runs once when the FastAPI application starts.
45
+ """
46
+ conn = None # Initialize conn to None to ensure it's closed in finally block even if connection fails
47
+ try:
48
+ conn = get_db_connection()
49
+ cursor = conn.cursor()
50
+ cursor.execute("""
51
+ CREATE TABLE IF NOT EXISTS items (
52
+ id INTEGER PRIMARY KEY AUTOINCREMENT,
53
+ name TEXT NOT NULL,
54
+ description TEXT
55
+ )
56
+ """)
57
+ conn.commit()
58
+ print(f"Database table 'items' checked/created successfully at {DATABASE_FILE}.")
59
+ except Exception as e:
60
+ print(f"Error during database startup: {e}")
61
+ # If critical tables cannot be created, the app might not function.
62
+ # Consider raising the exception to prevent the app from starting in a broken state.
63
+ finally:
64
+ if conn:
65
+ conn.close()
66
+
67
+ @app.get("/")
68
+ async def root():
69
+ """Root endpoint for the API."""
70
+ return {"message": "Welcome to the API!"}
71
 
72
  @app.post("/items/")
73
+ async def create_item(item: Item): # FastAPI automatically expects JSON body based on Pydantic model
74
+ """Creates a new item in the database."""
75
  conn = get_db_connection()
76
  cursor = conn.cursor()
77
  try:
78
  query = "INSERT INTO items (name, description) VALUES (?, ?)"
79
+ cursor.execute(query, (item.name, item.description)) # Access data via item.name, item.description
80
  conn.commit()
81
  return {"message": "Item created successfully", "id": cursor.lastrowid}
82
  except Exception as e:
83
+ conn.rollback() # Rollback changes if an error occurs
84
  raise HTTPException(status_code=500, detail=f"Error creating item: {e}")
85
  finally:
86
  cursor.close()
87
  conn.close()
88
 
89
+ @app.get("/items/")
90
+ async def read_items():
91
+ """Retrieves all items from the database."""
92
+ conn = get_db_connection()
93
+ cursor = conn.cursor()
94
+ try:
95
+ cursor.execute("SELECT * FROM items")
96
+ items = cursor.fetchall()
97
+ # Convert sqlite3.Row objects to dictionaries for JSON serialization
98
+ return {"items": [dict(item) for item in items]}
99
+ except Exception as e:
100
+ raise HTTPException(status_code=500, detail=f"Error reading items: {e}")
101
+ finally:
102
+ cursor.close()
103
+ conn.close()
104
+
105
+ @app.get("/items/{item_id}")
106
+ async def read_item(item_id: int):
107
+ """Retrieves a single item by its ID."""
108
+ conn = get_db_connection()
109
+ cursor = conn.cursor()
110
+ try:
111
+ cursor.execute("SELECT * FROM items WHERE id = ?", (item_id,))
112
+ item = cursor.fetchone()
113
+ if item is None:
114
+ raise HTTPException(status_code=404, detail="Item not found")
115
+ return dict(item)
116
+ except Exception as e:
117
+ raise HTTPException(status_code=500, detail=f"Error reading item: {e}")
118
+ finally:
119
+ cursor.close()
120
+ conn.close()
121
+
122
  @app.put("/items/{item_id}")
123
+ async def update_item(item_id: int, item: ItemUpdate): # Use ItemUpdate for partial updates
124
+ """Updates an existing item by its ID."""
125
  conn = get_db_connection()
126
  cursor = conn.cursor()
127
  try:
128
  updates = []
129
  params = []
130
 
131
+ if item.name is not None:
132
  updates.append("name = ?")
133
  params.append(item.name)
134
+ if item.description is not None:
135
  updates.append("description = ?")
136
  params.append(item.description)
137
 
138
  if not updates:
139
+ # If no fields were provided for update, return a 400 Bad Request
140
  raise HTTPException(status_code=400, detail="No fields to update provided")
141
 
142
  query = f"UPDATE items SET {', '.join(updates)} WHERE id = ?"
143
+ params.append(item_id) # Add item_id to the end of parameters for the WHERE clause
144
 
145
  cursor.execute(query, tuple(params))
146
  conn.commit()
147
 
148
  if cursor.rowcount == 0:
149
+ # If no rows were affected, the item with the given ID was not found
150
  raise HTTPException(status_code=404, detail="Item not found")
151
  return {"message": "Item updated successfully"}
152
+ except HTTPException: # Re-raise FastAPI's own HTTPExceptions
153
  raise
154
  except Exception as e:
155
+ conn.rollback() # Rollback changes if an error occurs
156
  raise HTTPException(status_code=500, detail=f"Error updating item: {e}")
157
  finally:
158
  cursor.close()
159
  conn.close()
160
 
161
+ @app.delete("/items/{item_id}")
162
+ async def delete_item(item_id: int):
163
+ """Deletes an item by its ID."""
164
+ conn = get_db_connection()
165
+ cursor = conn.cursor()
166
+ try:
167
+ cursor.execute("DELETE FROM items WHERE id = ?", (item_id,))
168
+ conn.commit()
169
+ if cursor.rowcount == 0:
170
+ # If no rows were affected, the item with the given ID was not found
171
+ raise HTTPException(status_code=404, detail="Item not found")
172
+ return {"message": "Item deleted successfully"}
173
+ except Exception as e:
174
+ conn.rollback() # Rollback changes if an error occurs
175
+ raise HTTPException(status_code=500, detail=f"Error deleting item: {e}")
176
+ finally:
177
+ cursor.close()
178
+ conn.close()