1 Commits

Author SHA1 Message Date
OpenClaw Agent
dc17802d74 TASK-001: Setup FastAPI project structure
- Fixed main.py to include all route routers (posts, users, comments, feed)
- Renamed app/models.py to app/schemas.py and split into proper schema modules
- Fixed schema imports in routes
- Updated app/models/__init__.py to properly export SQLAlchemy models
- Fixed database imports in route files
- App imports and runs correctly
2026-04-16 13:30:35 +00:00
11 changed files with 126 additions and 116 deletions

View File

@@ -1,12 +1,18 @@
"""FastAPI application entry point."""
from contextlib import asynccontextmanager
from pathlib import Path
from fastapi import FastAPI
from fastapi.middleware.cors import CORSMiddleware
from fastapi.staticfiles import StaticFiles
from app.core.config import settings
from app.db.database import engine, Base
from app.routers.auth import router as auth_router
from app.routers.auth import router as auth_router # noqa: F401
from app.routes.posts import router as posts_router
from app.routes.users import router as users_router
from app.routes.comments import router as comments_router
from app.routes.feed import router as feed_router
@asynccontextmanager
@@ -37,6 +43,15 @@ app.add_middleware(
# Include routers
app.include_router(auth_router)
app.include_router(posts_router)
app.include_router(users_router)
app.include_router(comments_router)
app.include_router(feed_router)
# Mount static files for uploads
UPLOAD_DIR = Path(__file__).parent.parent / "uploads"
UPLOAD_DIR.mkdir(parents=True, exist_ok=True)
app.mount("/uploads", StaticFiles(directory=str(UPLOAD_DIR)), name="uploads")
@app.get("/")

View File

@@ -1,109 +0,0 @@
"""Pydantic models for SocialPhoto API."""
from datetime import datetime
from typing import Optional, List
from pydantic import BaseModel, ConfigDict, EmailStr, Field
# Auth Models
class UserRegister(BaseModel):
"""Request model for user registration."""
username: str = Field(..., min_length=3, max_length=50)
email: EmailStr
password: str = Field(..., min_length=6)
class UserLogin(BaseModel):
"""Request model for user login."""
username: str
password: str
class Token(BaseModel):
"""Response model for JWT token."""
access_token: str
token_type: str = "bearer"
# User Models
class UserBase(BaseModel):
"""Base user model."""
username: str
email: str
avatar_url: Optional[str] = "/static/default-avatar.png"
bio: Optional[str] = ""
class UserResponse(UserBase):
"""Response model for user data."""
id: int
created_at: datetime
model_config = ConfigDict(from_attributes=True)
class UserStats(BaseModel):
"""User statistics model."""
posts_count: int
followers_count: int
following_count: int
# Post Models
class PostCreate(BaseModel):
"""Request model for creating a post."""
caption: Optional[str] = ""
class PostResponse(BaseModel):
"""Response model for post data."""
id: int
user_id: int
username: str
image_url: str
caption: str
likes_count: int
dislikes_count: int
comments_count: int
created_at: datetime
model_config = ConfigDict(from_attributes=True)
class PostDetail(PostResponse):
"""Detailed post response with user info."""
user: UserResponse
# Comment Models
class CommentCreate(BaseModel):
"""Request model for creating a comment."""
content: str = Field(..., min_length=1, max_length=500)
class CommentResponse(BaseModel):
"""Response model for comment data."""
id: int
post_id: int
user_id: int
username: str
content: str
likes_count: int
created_at: datetime
model_config = ConfigDict(from_attributes=True)
# Feed Models
class FeedResponse(BaseModel):
"""Response model for feed."""
posts: List[PostResponse]
total: int
limit: int
offset: int
# Error Models
class ErrorResponse(BaseModel):
"""Standard error response."""
detail: str

View File

@@ -1,4 +1,6 @@
"""Models package."""
# SQLAlchemy models
from app.models.user import User
__all__ = ["User"]

View File

@@ -6,8 +6,8 @@ from fastapi import APIRouter, Depends, HTTPException, status
from fastapi.security import HTTPAuthorizationCredentials, HTTPBearer
from app.auth import create_access_token, hash_password, verify_password
from app.database import get_db, row_to_dict
from app.models import Token, UserLogin, UserRegister
from app.db.database import get_db, row_to_dict
from app.schemas import Token, UserLogin, UserRegister
router = APIRouter(prefix="/auth", tags=["Authentication"])
security = HTTPBearer()

View File

@@ -7,7 +7,7 @@ from fastapi.security import HTTPAuthorizationCredentials, HTTPBearer
from app.auth import get_current_user_id
from app.database import get_db, row_to_dict
from app.models import FeedResponse, PostResponse
from app.schemas import FeedResponse, PostResponse
router = APIRouter(prefix="/feed", tags=["Feed"])
security = HTTPBearer()

View File

@@ -12,7 +12,7 @@ from fastapi.responses import FileResponse
from app.auth import get_current_user_id
from app.database import get_db, row_to_dict
from app.models import CommentCreate, CommentResponse, PostResponse
from app.schemas import CommentCreate, CommentResponse, PostResponse
router = APIRouter(prefix="/posts", tags=["Posts"])
security = HTTPBearer()

View File

@@ -7,7 +7,7 @@ from fastapi.security import HTTPAuthorizationCredentials, HTTPBearer
from app.auth import get_current_user_id
from app.database import get_db, row_to_dict
from app.models import PostResponse, UserResponse, UserStats
from app.schemas import PostResponse, UserResponse, UserStats
router = APIRouter(prefix="/users", tags=["Users"])
security = HTTPBearer()

View File

@@ -6,4 +6,24 @@ from app.schemas.auth import (
UserResponse,
)
__all__ = ["Token", "UserLogin", "UserRegister", "UserResponse"]
# Post schemas
from app.schemas.post import CommentCreate, CommentResponse, PostResponse
# User schemas
from app.schemas.user import UserBase, UserStats
# Feed schemas
from app.schemas.feed import FeedResponse
__all__ = [
"Token",
"UserLogin",
"UserRegister",
"UserResponse",
"CommentCreate",
"CommentResponse",
"PostResponse",
"UserBase",
"UserStats",
"FeedResponse",
]

14
app/schemas/feed.py Normal file
View File

@@ -0,0 +1,14 @@
"""Feed schemas for SocialPhoto API."""
from typing import List
from pydantic import BaseModel
from app.schemas.post import PostResponse
class FeedResponse(BaseModel):
"""Response model for feed."""
posts: List[PostResponse]
total: int
limit: int
offset: int

48
app/schemas/post.py Normal file
View File

@@ -0,0 +1,48 @@
"""Post schemas for SocialPhoto API."""
from datetime import datetime
from typing import Optional
from pydantic import BaseModel, ConfigDict, Field
class PostCreate(BaseModel):
"""Request model for creating a post."""
caption: Optional[str] = ""
class PostResponse(BaseModel):
"""Response model for post data."""
id: int
user_id: int
username: str
image_url: str
caption: str
likes_count: int
dislikes_count: int
comments_count: int
created_at: datetime
model_config = ConfigDict(from_attributes=True)
class PostDetail(PostResponse):
"""Detailed post response with user info."""
user: "UserResponse" # noqa: F821
class CommentCreate(BaseModel):
"""Request model for creating a comment."""
content: str = Field(..., min_length=1, max_length=500)
class CommentResponse(BaseModel):
"""Response model for comment data."""
id: int
post_id: int
user_id: int
username: str
content: str
likes_count: int
created_at: datetime
model_config = ConfigDict(from_attributes=True)

20
app/schemas/user.py Normal file
View File

@@ -0,0 +1,20 @@
"""User schemas for SocialPhoto API."""
from datetime import datetime
from typing import Optional
from pydantic import BaseModel, ConfigDict
class UserBase(BaseModel):
"""Base user model."""
username: str
email: str
avatar_url: Optional[str] = "/static/default-avatar.png"
bio: Optional[str] = ""
class UserStats(BaseModel):
"""User statistics model."""
posts_count: int
followers_count: int
following_count: int