1616
1717import models
1818from database import Base , engine , get_db
19- from schemas import (
20- PostCreate ,
21- PostResponse ,
22- PostUpdate ,
23- UserCreate ,
24- UserResponse ,
25- UserUpdate ,
26- )
19+
20+ from routers import users , posts
2721
2822
2923@asynccontextmanager
@@ -43,6 +37,9 @@ async def lifespan(_app: FastAPI):
4337
4438templates = Jinja2Templates (directory = "templates" )
4539
40+ app .include_router (users .router , prefix = "/api/users" , tags = ["users" ])
41+ app .include_router (posts .router , prefix = "/api/posts" , tags = ["posts" ])
42+
4643
4744@app .get ("/" , include_in_schema = False , name = "home" )
4845@app .get ("/posts" , include_in_schema = False , name = "posts" )
@@ -106,248 +103,6 @@ async def user_posts_page(
106103 )
107104
108105
109- @app .post (
110- "/api/users" ,
111- response_model = UserResponse ,
112- status_code = status .HTTP_201_CREATED ,
113- )
114- async def create_user (user : UserCreate , db : Annotated [AsyncSession , Depends (get_db )]):
115- result = await db .execute (
116- select (models .User ).where (models .User .username == user .username ),
117- )
118- existing_user = result .scalars ().first ()
119- if existing_user :
120- raise HTTPException (
121- status_code = status .HTTP_400_BAD_REQUEST ,
122- detail = "Username already exists" ,
123- )
124-
125- result = await db .execute (
126- select (models .User ).where (models .User .email == user .email ),
127- )
128- existing_email = result .scalars ().first ()
129- if existing_email :
130- raise HTTPException (
131- status_code = status .HTTP_400_BAD_REQUEST ,
132- detail = "Email already registered" ,
133- )
134-
135- new_user = models .User (
136- username = user .username ,
137- email = user .email ,
138- )
139- db .add (new_user )
140- await db .commit ()
141- await db .refresh (new_user )
142- return new_user
143-
144-
145- @app .get ("/api/users/{user_id}" , response_model = UserResponse )
146- async def get_user (user_id : int , db : Annotated [AsyncSession , Depends (get_db )]):
147- result = await db .execute (select (models .User ).where (models .User .id == user_id ))
148- user = result .scalars ().first ()
149- if user :
150- return user
151- raise HTTPException (status_code = status .HTTP_404_NOT_FOUND , detail = "User not found" )
152-
153-
154- @app .get ("/api/users/{user_id}/posts" , response_model = list [PostResponse ])
155- async def get_user_posts (user_id : int , db : Annotated [AsyncSession , Depends (get_db )]):
156- result = await db .execute (select (models .User ).where (models .User .id == user_id ))
157- user = result .scalars ().first ()
158- if not user :
159- raise HTTPException (
160- status_code = status .HTTP_404_NOT_FOUND ,
161- detail = "User not found" ,
162- )
163- result = await db .execute (
164- select (models .Post )
165- .options (selectinload (models .Post .author ))
166- .where (models .Post .user_id == user_id ),
167- )
168- posts = result .scalars ().all ()
169- return posts
170-
171-
172- @app .patch ("/api/users/{user_id}" , response_model = UserResponse )
173- async def update_user (
174- user_id : int ,
175- user_update : UserUpdate ,
176- db : Annotated [AsyncSession , Depends (get_db )],
177- ):
178- result = await db .execute (select (models .User ).where (models .User .id == user_id ))
179- user = result .scalars ().first ()
180- if not user :
181- raise HTTPException (
182- status_code = status .HTTP_404_NOT_FOUND ,
183- detail = "User not found" ,
184- )
185- if user_update .username is not None and user_update .username != user .username :
186- result = await db .execute (
187- select (models .User ).where (models .User .username == user_update .username ),
188- )
189- existing_user = result .scalars ().first ()
190- if existing_user :
191- raise HTTPException (
192- status_code = status .HTTP_400_BAD_REQUEST ,
193- detail = "Username already exists" ,
194- )
195- if user_update .email is not None and user_update .email != user .email :
196- result = await db .execute (
197- select (models .User ).where (models .User .email == user_update .email ),
198- )
199- existing_email = result .scalars ().first ()
200- if existing_email :
201- raise HTTPException (
202- status_code = status .HTTP_400_BAD_REQUEST ,
203- detail = "Email already registered" ,
204- )
205-
206- if user_update .username is not None :
207- user .username = user_update .username
208- if user_update .email is not None :
209- user .email = user_update .email
210- if user_update .image_file is not None :
211- user .image_file = user_update .image_file
212-
213- await db .commit ()
214- await db .refresh (user )
215- return user
216-
217-
218- @app .delete ("/api/users/{user_id}" , status_code = status .HTTP_204_NO_CONTENT )
219- async def delete_user (user_id : int , db : Annotated [AsyncSession , Depends (get_db )]):
220- result = await db .execute (select (models .User ).where (models .User .id == user_id ))
221- user = result .scalars ().first ()
222- if not user :
223- raise HTTPException (
224- status_code = status .HTTP_404_NOT_FOUND ,
225- detail = "User not found" ,
226- )
227-
228- await db .delete (user )
229- await db .commit ()
230-
231-
232- @app .get ("/api/posts" , response_model = list [PostResponse ])
233- async def get_posts (db : Annotated [AsyncSession , Depends (get_db )]):
234- result = await db .execute (
235- select (models .Post ).options (selectinload (models .Post .author )),
236- )
237- posts = result .scalars ().all ()
238- return posts
239-
240-
241- @app .post (
242- "/api/posts" ,
243- response_model = PostResponse ,
244- status_code = status .HTTP_201_CREATED ,
245- )
246- async def create_post (post : PostCreate , db : Annotated [AsyncSession , Depends (get_db )]):
247- result = await db .execute (
248- select (models .User ).where (models .User .id == post .user_id ),
249- )
250- user = result .scalars ().first ()
251- if not user :
252- raise HTTPException (
253- status_code = status .HTTP_404_NOT_FOUND ,
254- detail = "User not found" ,
255- )
256-
257- new_post = models .Post (
258- title = post .title ,
259- content = post .content ,
260- user_id = post .user_id ,
261- )
262- db .add (new_post )
263- await db .commit ()
264- await db .refresh (new_post , attribute_names = ["author" ])
265- return new_post
266-
267-
268- @app .get ("/api/posts/{post_id}" , response_model = PostResponse )
269- async def get_post (post_id : int , db : Annotated [AsyncSession , Depends (get_db )]):
270- result = await db .execute (
271- select (models .Post )
272- .options (selectinload (models .Post .author ))
273- .where (models .Post .id == post_id ),
274- )
275- post = result .scalars ().first ()
276- if post :
277- return post
278- raise HTTPException (status_code = status .HTTP_404_NOT_FOUND , detail = "Post not found" )
279-
280-
281- @app .put ("/api/posts/{post_id}" , response_model = PostResponse )
282- async def update_post_full (
283- post_id : int ,
284- post_data : PostCreate ,
285- db : Annotated [AsyncSession , Depends (get_db )],
286- ):
287- result = await db .execute (select (models .Post ).where (models .Post .id == post_id ))
288- post = result .scalars ().first ()
289- if not post :
290- raise HTTPException (
291- status_code = status .HTTP_404_NOT_FOUND ,
292- detail = "Post not found" ,
293- )
294- if post_data .user_id != post .user_id :
295- result = await db .execute (
296- select (models .User ).where (models .User .id == post_data .user_id ),
297- )
298- user = result .scalars ().first ()
299- if not user :
300- raise HTTPException (
301- status_code = status .HTTP_404_NOT_FOUND ,
302- detail = "User not found" ,
303- )
304-
305- post .title = post_data .title
306- post .content = post_data .content
307- post .user_id = post_data .user_id
308-
309- await db .commit ()
310- await db .refresh (post , attribute_names = ["author" ])
311- return post
312-
313-
314- @app .patch ("/api/posts/{post_id}" , response_model = PostResponse )
315- async def update_post_partial (
316- post_id : int ,
317- post_data : PostUpdate ,
318- db : Annotated [AsyncSession , Depends (get_db )],
319- ):
320- result = await db .execute (select (models .Post ).where (models .Post .id == post_id ))
321- post = result .scalars ().first ()
322- if not post :
323- raise HTTPException (
324- status_code = status .HTTP_404_NOT_FOUND ,
325- detail = "Post not found" ,
326- )
327-
328- update_data = post_data .model_dump (exclude_unset = True )
329- for field , value in update_data .items ():
330- setattr (post , field , value )
331-
332- await db .commit ()
333- await db .refresh (post , attribute_names = ["author" ])
334- return post
335-
336-
337- @app .delete ("/api/posts/{post_id}" , status_code = status .HTTP_204_NO_CONTENT )
338- async def delete_post (post_id : int , db : Annotated [AsyncSession , Depends (get_db )]):
339- result = await db .execute (select (models .Post ).where (models .Post .id == post_id ))
340- post = result .scalars ().first ()
341- if not post :
342- raise HTTPException (
343- status_code = status .HTTP_404_NOT_FOUND ,
344- detail = "Post not found" ,
345- )
346-
347- await db .delete (post )
348- await db .commit ()
349-
350-
351106@app .exception_handler (StarletteHTTPException )
352107async def general_http_exception_handler (
353108 request : Request ,
0 commit comments