|
9 | 9 | from fastapi.exceptions import RequestValidationError |
10 | 10 | from fastapi.staticfiles import StaticFiles |
11 | 11 | from fastapi.templating import Jinja2Templates |
12 | | -from sqlalchemy import select |
| 12 | +from sqlalchemy import select, func |
13 | 13 | from sqlalchemy.ext.asyncio import AsyncSession |
14 | 14 | from sqlalchemy.orm import selectinload |
15 | 15 | from starlette.exceptions import HTTPException as StarletteHTTPException |
16 | | - |
17 | 16 | import models |
18 | 17 | from database import Base, engine, get_db |
19 | | - |
| 18 | +from config import settings |
20 | 19 | from routers import users, posts |
21 | 20 |
|
22 | 21 |
|
@@ -44,16 +43,28 @@ async def lifespan(_app: FastAPI): |
44 | 43 | @app.get("/", include_in_schema=False, name="home") |
45 | 44 | @app.get("/posts", include_in_schema=False, name="posts") |
46 | 45 | async def home(request: Request, db: Annotated[AsyncSession, Depends(get_db)]): |
| 46 | + count_result = await db.execute(select(func.count()).select_from(models.Post)) |
| 47 | + total = count_result.scalar() or 0 |
| 48 | + |
47 | 49 | result = await db.execute( |
48 | 50 | select(models.Post) |
49 | 51 | .options(selectinload(models.Post.author)) |
50 | 52 | .order_by(models.Post.date_posted.desc()) |
| 53 | + .limit(settings.posts_per_page), |
51 | 54 | ) |
52 | 55 | posts = result.scalars().all() |
| 56 | + |
| 57 | + has_more = len(posts) < total |
| 58 | + |
53 | 59 | return templates.TemplateResponse( |
54 | 60 | request, |
55 | 61 | "home.html", |
56 | | - {"posts": posts, "title": "Home"}, |
| 62 | + { |
| 63 | + "posts": posts, |
| 64 | + "title": "Home", |
| 65 | + "limit": settings.posts_per_page, |
| 66 | + "has_more": has_more, |
| 67 | + }, |
57 | 68 | ) |
58 | 69 |
|
59 | 70 |
|
@@ -92,17 +103,35 @@ async def user_posts_page( |
92 | 103 | status_code=status.HTTP_404_NOT_FOUND, |
93 | 104 | detail="User not found", |
94 | 105 | ) |
| 106 | + |
| 107 | + count_result = await db.execute( |
| 108 | + select(func.count()) |
| 109 | + .select_from(models.Post) |
| 110 | + .where(models.Post.user_id == user_id), |
| 111 | + ) |
| 112 | + total = count_result.scalar() or 0 |
| 113 | + |
95 | 114 | result = await db.execute( |
96 | 115 | select(models.Post) |
97 | 116 | .options(selectinload(models.Post.author)) |
98 | 117 | .where(models.Post.user_id == user_id) |
99 | 118 | .order_by(models.Post.date_posted.desc()) |
| 119 | + .limit(settings.posts_per_page), |
100 | 120 | ) |
101 | 121 | posts = result.scalars().all() |
| 122 | + |
| 123 | + has_more = len(posts) < total |
| 124 | + |
102 | 125 | return templates.TemplateResponse( |
103 | 126 | request, |
104 | 127 | "user_posts.html", |
105 | | - {"posts": posts, "user": user, "title": f"{user.username}'s Posts"}, |
| 128 | + { |
| 129 | + "posts": posts, |
| 130 | + "user": user, |
| 131 | + "title": f"{user.username}'s Posts", |
| 132 | + "limit": settings.posts_per_page, |
| 133 | + "has_more": has_more, |
| 134 | + }, |
106 | 135 | ) |
107 | 136 |
|
108 | 137 |
|
@@ -131,6 +160,25 @@ async def account_page(request: Request): |
131 | 160 | {"title": "Account"}, |
132 | 161 | ) |
133 | 162 |
|
| 163 | +@app.get("/forgot-password", include_in_schema=False) |
| 164 | +async def forgot_password_page(request: Request): |
| 165 | + return templates.TemplateResponse( |
| 166 | + request, |
| 167 | + "forgot_password.html", |
| 168 | + {"title": "Forgot Password"}, |
| 169 | + ) |
| 170 | + |
| 171 | + |
| 172 | +@app.get("/reset-password", include_in_schema=False) |
| 173 | +async def reset_password_page(request: Request): |
| 174 | + response = templates.TemplateResponse( |
| 175 | + request, |
| 176 | + "reset_password.html", |
| 177 | + {"title": "Reset Password"}, |
| 178 | + ) |
| 179 | + response.headers["Referrer-Policy"] = "no-referrer" |
| 180 | + return response |
| 181 | + |
134 | 182 |
|
135 | 183 | @app.exception_handler(StarletteHTTPException) |
136 | 184 | async def general_http_exception_handler( |
|
0 commit comments