Update generated backend for blog_app

This commit is contained in:
Idris Abdurrahman 2025-03-20 12:08:13 +01:00
parent 26d01d18c1
commit 5f5c59bd06
17 changed files with 281 additions and 6 deletions

View File

@ -0,0 +1,24 @@
Here's the `dependencies.py` file for the specified path `app/api/core/dependencies/`:
```python
from contextlib import contextmanager
from sqlalchemy.orm import Session
from app.api.db.database import SessionLocal
@contextmanager
def get_db() -> Session:
db = SessionLocal()
try:
yield db
finally:
db.close()
```
This file defines a context manager function `get_db` that creates a new SQLAlchemy `Session` using the `SessionLocal` imported from `app.api.db.database`. The session is yielded within the context manager, and it is automatically closed when the context manager exits, ensuring proper resource management.
To use this function in your application, you can import it and use it as a dependency in your API routes or services that require database access. For example:
```python
from fastapi import Depends
from app.api.core.dependencies import get_db
# In your API route or service
def my_function(db: Session = Depends(get_db)):
# Use the database session 'db' here
...
```
By using the `Depends` function from FastAPI, the `get_db` function will be called for each request, and the resulting database session will be injected as a dependency into your function.

View File

@ -0,0 +1,28 @@
Here's the `activity_tracker.py` file with the `ActivityTrackerMiddleware` class that logs request method, URL, and processing time:
```python
import time
from starlette.middleware.base import BaseHTTPMiddleware
from starlette.requests import Request
from starlette.responses import Response
class ActivityTrackerMiddleware(BaseHTTPMiddleware):
async def dispatch(self, request: Request, call_next):
start_time = time.time()
request_method = request.method
request_url = str(request.url)
response = await call_next(request)
process_time = time.time() - start_time
log_message = f"{request_method} {request_url} - {process_time:.6f} seconds"
print(log_message)
return response
```
This middleware class extends the `BaseHTTPMiddleware` class from Starlette, which is the underlying ASGI server used by FastAPI. The `dispatch` method is overridden to handle the request and response lifecycle.
Here's what the code does:
To use this middleware in your FastAPI application, you need to add it to the list of middleware in your `main.py` file or wherever you create the FastAPI application instance:
```python
from fastapi import FastAPI
from app.api.core.middleware.activity_tracker import ActivityTrackerMiddleware
app = FastAPI()
app.add_middleware(ActivityTrackerMiddleware)
# Your application routes and other configurations
```
With this middleware in place, every incoming request to your FastAPI application will be logged with the request method, URL, and processing time.

17
app/api/db/database.py Normal file
View File

@ -0,0 +1,17 @@
# app/api/db/database.py
from sqlalchemy import create_engine
from sqlalchemy.ext.declarative import declarative_base
from sqlalchemy.orm import sessionmaker
# Configure SQLite database
SQLALCHEMY_DATABASE_URL = "sqlite:///./blog_app.db"
# Create the SQLAlchemy engine
engine = create_engine(
SQLALCHEMY_DATABASE_URL, connect_args={"check_same_thread": False}
)
# Create a SessionLocal class for database sessions
SessionLocal = sessionmaker(autocommit=False, autoflush=False, bind=engine)
# Create a Base class for models
Base = declarative_base()
```
This code defines the necessary components for interacting with a SQLite database using SQLAlchemy in a FastAPI application named `blog_app`.
This `database.py` file should be placed in the `app/api/db/` directory of the FastAPI project, following the recommended project structure.

10
app/api/v1/models/and.py Normal file
View File

@ -0,0 +1,10 @@
from sqlalchemy import Column, Integer, String, ForeignKey
from sqlalchemy.orm import relationship
from app.api.db.database import Base
class And(Base):
__tablename__ = "ands"
id = Column(Integer, primary_key=True, index=True)
title = Column(String)
body = Column(String)
author_id = Column(Integer, ForeignKey("users.id"))
author = relationship("User", back_populates="ands")

View File

@ -0,0 +1,11 @@
from sqlalchemy import Column, Integer, String, Text, ForeignKey
from sqlalchemy.orm import relationship
from app.api.db.database import Base
class Comments(Base):
__tablename__ = "comments"
id = Column(Integer, primary_key=True, index=True)
content = Column(Text)
post_id = Column(Integer, ForeignKey("posts.id"))
author_id = Column(Integer, ForeignKey("users.id"))
post = relationship("Posts", back_populates="comments")
author = relationship("Users", back_populates="comments")

View File

@ -0,0 +1,10 @@
from sqlalchemy import Column, Integer, String, Text, ForeignKey
from sqlalchemy.orm import relationship
from app.api.db.database import Base
class Posts(Base):
__tablename__ = "posts"
id = Column(Integer, primary_key=True, index=True)
title = Column(String, nullable=False)
content = Column(Text, nullable=False)
author_id = Column(Integer, ForeignKey("users.id"), nullable=False)
author = relationship("Users", back_populates="posts")

View File

@ -0,0 +1,9 @@
from sqlalchemy import Column, Integer, String
from app.api.db.database import Base
class User(Base):
__tablename__ = "users"
id = Column(Integer, primary_key=True, index=True)
username = Column(String, unique=True, index=True)
email = Column(String, unique=True, index=True)
password = Column(String)
is_active = Column(Integer, default=1)

View File

@ -0,0 +1,10 @@
from fastapi import APIRouter
from .posts import router as posts_router
from .comments import router as comments_router
from .user import router as user_router
from .and import router as and_router
router = APIRouter()
router.include_router(posts_router, prefix="/posts", tags=["posts"])
router.include_router(comments_router, prefix="/comments", tags=["comments"])
router.include_router(user_router, prefix="/users", tags=["users"])
router.include_router(and_router, prefix="/and", tags=["and"])

24
app/api/v1/routes/and.py Normal file
View File

@ -0,0 +1,24 @@
from typing import List
from fastapi import APIRouter, Depends, HTTPException
from sqlalchemy.orm import Session
from app.api.v1.models.and import And
from app.api.v1.schemas.and import AndCreate, AndResponse
from app.api.core.dependencies.dependencies import get_db
router = APIRouter()
@router.get("/ands", response_model=List[AndResponse])
def read_ands(db: Session = Depends(get_db)):
ands = db.query(And).all()
return ands
@router.post("/ands", response_model=AndResponse)
def create_and(and_data: AndCreate, db: Session = Depends(get_db)):
and_instance = And(**and_data.dict())
db.add(and_instance)
db.commit()
db.refresh(and_instance)
return and_instance
@router.get("/ands/{id}", response_model=AndResponse)
def read_and(id: int, db: Session = Depends(get_db)):
and_instance = db.query(And).get(id)
if not and_instance:
raise HTTPException(status_code=404, detail="And not found")
return and_instance

View File

@ -0,0 +1,24 @@
from typing import List
from fastapi import APIRouter, Depends, HTTPException
from sqlalchemy.orm import Session
from app.api.v1.models.comments import Comments
from app.api.v1.schemas.comments import CommentsCreate, CommentsResponse
from app.api.core.dependencies.dependencies import get_db
router = APIRouter()
@router.get("/commentss", response_model=List[CommentsResponse])
def read_commentss(db: Session = Depends(get_db)):
commentss = db.query(Comments).all()
return commentss
@router.post("/commentss", response_model=CommentsResponse)
def create_comments(comments: CommentsCreate, db: Session = Depends(get_db)):
db_comments = Comments(**comments.dict())
db.add(db_comments)
db.commit()
db.refresh(db_comments)
return db_comments
@router.get("/commentss/{id}", response_model=CommentsResponse)
def read_comments(id: int, db: Session = Depends(get_db)):
db_comments = db.query(Comments).get(id)
if not db_comments:
raise HTTPException(status_code=404, detail="Comments not found")
return db_comments

View File

@ -0,0 +1,24 @@
from typing import List
from fastapi import APIRouter, Depends, HTTPException
from sqlalchemy.orm import Session
from app.api.v1.models.posts import Posts
from app.api.v1.schemas.posts import PostsCreate, PostsResponse
from app.api.core.dependencies.dependencies import get_db
router = APIRouter()
@router.get("/postss", response_model=List[PostsResponse])
def read_postss(db: Session = Depends(get_db)):
postss = db.query(Posts).all()
return postss
@router.post("/postss", response_model=PostsResponse)
def create_posts(posts: PostsCreate, db: Session = Depends(get_db)):
db_posts = Posts(**posts.dict())
db.add(db_posts)
db.commit()
db.refresh(db_posts)
return db_posts
@router.get("/postss/{id}", response_model=PostsResponse)
def read_posts(id: int, db: Session = Depends(get_db)):
posts = db.query(Posts).get(id)
if not posts:
raise HTTPException(status_code=404, detail="Posts not found")
return posts

24
app/api/v1/routes/user.py Normal file
View File

@ -0,0 +1,24 @@
from typing import List
from fastapi import APIRouter, Depends, HTTPException
from sqlalchemy.orm import Session
from app.api.v1.models.user import User
from app.api.v1.schemas.user import UserCreate, UserResponse
from app.api.core.dependencies.dependencies import get_db
router = APIRouter()
@router.get("/users", response_model=List[UserResponse])
def get_users(db: Session = Depends(get_db)):
users = db.query(User).all()
return users
@router.post("/users", response_model=UserResponse)
def create_user(user: UserCreate, db: Session = Depends(get_db)):
db_user = User(**user.dict())
db.add(db_user)
db.commit()
db.refresh(db_user)
return db_user
@router.get("/users/{user_id}", response_model=UserResponse)
def get_user(user_id: int, db: Session = Depends(get_db)):
db_user = db.query(User).filter(User.id == user_id).first()
if not db_user:
raise HTTPException(status_code=404, detail="User not found")
return db_user

14
app/api/v1/schemas/and.py Normal file
View File

@ -0,0 +1,14 @@
from pydantic import BaseModel
from app.db.base import Base
from typing import Optional
class AndBase(BaseModel):
title: str
content: str
class AndCreate(AndBase):
pass
class And(AndBase):
id: int
is_published: bool
rating: Optional[int] = None
class Config:
orm_mode = True

View File

@ -0,0 +1,16 @@
from typing import Optional
from datetime import datetime
from pydantic import BaseModel
class CommentsCreate(BaseModel):
text: str
post_id: int
user_id: int
class Comments(BaseModel):
id: int
text: str
post_id: int
user_id: int
created_at: datetime
updated_at: Optional[datetime] = None
class Config:
orm_mode = True

View File

@ -0,0 +1,14 @@
from pydantic import BaseModel
from typing import Optional
from datetime import datetime
class PostsBase(BaseModel):
title: str
content: str
class PostsCreate(PostsBase):
pass
class Posts(PostsBase):
id: int
created_at: datetime
updated_at: Optional[datetime] = None
class Config:
orm_mode = True

View File

@ -0,0 +1,10 @@
from pydantic import BaseModel, EmailStr
class UserBase(BaseModel):
email: EmailStr
class UserCreate(UserBase):
password: str
class User(UserBase):
id: int
is_active: bool
class Config:
orm_mode = True

18
main.py
View File

@ -1,7 +1,13 @@
from fastapi import FastAPI
app = FastAPI(title="Generated Backend")
@app.get("/")
def read_root():
return {"message": "Welcome to the generated backend"}
from app.api.db.database import Base, engine
from app.api.v1.routes import router as v1_router
from app.api.core.middleware.activity_tracker import ActivityTrackerMiddleware
app = FastAPI()
app.include_router(v1_router, prefix="/v1")
app.add_middleware(ActivityTrackerMiddleware)
@app.on_event("startup")
async def startup_event():
Base.metadata.create_all(bind=engine)
if __name__ == "__main__":
import uvicorn
uvicorn.run("main:app", host="0.0.0.0", reload=True)