Update generated backend for blog_app with entities: posts, comments, tags, user
This commit is contained in:
parent
186e46d24f
commit
64dcbd6144
@ -1,25 +1,32 @@
|
||||
Here's the `dependencies.py` file for the `app/api/core/dependencies/` directory in the `blog_app_igblf` FastAPI backend project:
|
||||
Here's the `dependencies.py` file with the `get_db` function:
|
||||
|
||||
|
||||
from databases import Database
|
||||
from typing import Generator
|
||||
|
||||
from sqlalchemy import create_engine
|
||||
from sqlalchemy.orm import sessionmaker
|
||||
from sqlalchemy.ext.declarative import declarative_base
|
||||
|
||||
from app.core.settings import settings
|
||||
from app.core.config import settings
|
||||
|
||||
engine = create_engine(
|
||||
settings.DATABASE_URL, connect_args={"check_same_thread": False}
|
||||
settings.SQLALCHEMY_DATABASE_URI,
|
||||
connect_args={"check_same_thread": False},
|
||||
|
||||
SessionLocal = sessionmaker(autocommit=False, autoflush=False, bind=engine)
|
||||
|
||||
Base = declarative_base()
|
||||
|
||||
def get_db():
|
||||
db = SessionLocal()
|
||||
def get_db() -> Generator:
|
||||
|
||||
try:
|
||||
db = SessionLocal()
|
||||
yield db
|
||||
finally:
|
||||
db.close()
|
||||
|
||||
This `dependencies.py` file contains the following components:
|
||||
Explanation:
|
||||
|
||||
1. We import the necessary modules: `typing` for type hints, `create_engine` and `sessionmaker` from SQLAlchemy for creating the database engine and session factory, and `settings` from `app.core.config` for accessing the database URI.
|
||||
|
||||
|
||||
|
||||
4. The `get_db` function is a dependency function that returns a SQLAlchemy session. It creates a new session using `SessionLocal()`, yields it to the requesting function, and closes the session after the requesting function has finished executing.
|
@ -1,63 +1,58 @@
|
||||
Here's an example of an `activity_tracker.py` file that defines middleware for a FastAPI backend named 'blog_app' using SQLite and SQLAlchemy:
|
||||
|
||||
|
||||
from datetime import datetime
|
||||
from typing import Callable, Awaitable
|
||||
from sqlalchemy.orm import Session
|
||||
from fastapi import Request, Response
|
||||
from app.db.session import get_db
|
||||
from app.db.models import ActivityLog
|
||||
from typing import Callable, Awaitable
|
||||
from datetime import datetime
|
||||
|
||||
async def log_activity(request: Request, call_next: Callable[[Request], Awaitable[Response]]) -> Response:
|
||||
|
||||
async def activity_tracker_middleware(request: Request, call_next: Callable[[Request], Awaitable[Response]]):
|
||||
start_time = datetime.now()
|
||||
response = await call_next(request)
|
||||
process_time = (datetime.now() - start_time).total_seconds() * 1000
|
||||
|
||||
try:
|
||||
db: Session = next(get_db())
|
||||
activity_log = ActivityLog(
|
||||
path=str(request.url.path),
|
||||
method=request.method,
|
||||
status_code=response.status_code,
|
||||
process_time=process_time,
|
||||
ip_address=request.client.host,
|
||||
user_agent=request.headers.get("User-Agent"),
|
||||
)
|
||||
db.add(activity_log)
|
||||
db.commit()
|
||||
except Exception as e:
|
||||
print(f"Error logging activity: {e}")
|
||||
finally:
|
||||
db.close()
|
||||
response: Response = await call_next(request)
|
||||
|
||||
end_time = datetime.now()
|
||||
response_time = end_time - start_time
|
||||
|
||||
log_activity(request, response, response_time)
|
||||
|
||||
return response
|
||||
|
||||
def log_activity(request: Request, response: Response, response_time: datetime.timedelta):
|
||||
user_id = get_user_id(request)
|
||||
endpoint = request.url.path
|
||||
method = request.method
|
||||
status_code = response.status_code
|
||||
|
||||
Here's a breakdown of the code:
|
||||
log_entry = {
|
||||
"user_id": user_id,
|
||||
"endpoint": endpoint,
|
||||
"method": method,
|
||||
"status_code": status_code,
|
||||
"response_time": str(response_time),
|
||||
"timestamp": datetime.now()
|
||||
}
|
||||
save_activity_log(log_entry)
|
||||
|
||||
print(log_entry)
|
||||
|
||||
def get_user_id(request: Request) -> str:
|
||||
user_id = request.headers.get("X-User-ID")
|
||||
return user_id or "anonymous"
|
||||
|
||||
3. Inside the `log_activity` function, the start time is recorded using `datetime.now()`.
|
||||
def save_activity_log(log_entry: dict):
|
||||
from app.db.database import SessionLocal
|
||||
from app.db.models import ActivityLog
|
||||
|
||||
db = SessionLocal()
|
||||
activity_log = ActivityLog(**log_entry)
|
||||
db.add(activity_log)
|
||||
db.commit()
|
||||
db.close()
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
8. The `ActivityLog` instance is added to the database session using `db.add(activity_log)`, and the changes are committed using `db.commit()`.
|
||||
from app.api.core.middleware.activity_tracker import activity_tracker_middleware
|
||||
|
||||
9. If an exception occurs during the database operation, an error message is printed (you may want to implement more robust error handling).
|
||||
app.add_middleware(activity_tracker_middleware)
|
||||
|
||||
10. Finally, the database session is closed using `db.close()`.
|
||||
|
||||
|
||||
To use this middleware in your FastAPI application, you need to include it in the middleware stack. You can do this by adding the following code to your `main.py` file or wherever you configure your FastAPI application:
|
||||
|
||||
from fastapi import FastAPI
|
||||
from app.api.core.middleware.activity_tracker import log_activity
|
||||
|
||||
app = FastAPI()
|
||||
app.middleware("http")(log_activity)
|
||||
|
||||
|
||||
|
||||
Note: This example assumes that you have already defined the `ActivityLog` model in your `app.db.models` module and set up the necessary database connections and session management.
|
||||
Note: This code assumes that you have a properly configured FastAPI project structure with SQLite and SQLAlchemy integration. You may need to adjust the imports and paths based on your project's structure.
|
@ -1,13 +1,15 @@
|
||||
Sure, here's the `database.py` file for the `app/api/db/` directory, which configures SQLite with `blog_app.db` using SQLAlchemy:
|
||||
Here's the `database.py` file for the `blog_app` FastAPI backend, configured with SQLite using SQLAlchemy:
|
||||
|
||||
|
||||
from sqlalchemy import create_engine
|
||||
from sqlalchemy.ext.declarative import declarative_base
|
||||
from sqlalchemy.orm import sessionmaker
|
||||
|
||||
SQLALCHEMY_DATABASE_URL = "sqlite:///blog_app.db"
|
||||
SQLALCHEMY_DATABASE_URL = "sqlite:///./blog_app.db"
|
||||
|
||||
engine = create_engine(
|
||||
SQLALCHEMY_DATABASE_URL, connect_args={"check_same_thread": False}
|
||||
|
||||
SessionLocal = sessionmaker(autocommit=False, autoflush=False, bind=engine)
|
||||
|
||||
Base = declarative_base()
|
||||
@ -19,8 +21,9 @@ def get_db():
|
||||
finally:
|
||||
db.close()
|
||||
|
||||
Here's a breakdown of the code:
|
||||
Explanation:
|
||||
|
||||
1. We import the necessary modules from SQLAlchemy: `create_engine`, `declarative_base`, and `sessionmaker`.
|
||||
|
||||
2. We define the `SQLALCHEMY_DATABASE_URL` as a string with the SQLite database file path (`blog_app.db`).
|
||||
2. We define the SQLite database URL using `SQLALCHEMY_DATABASE_URL = "sqlite:///./blog_app.db"`. This will create a new SQLite database file named `blog_app.db` in the current directory if it doesn't exist, or use the existing one if it does.
|
||||
3. We create the SQLAlchemy engine using `create_engine(SQLALCHEMY_DATABASE_URL, connect_args={"check_same_thread": False})`. The `connect_args` parameter is required for SQLite to avoid threading issues.
|
||||
5. We create a `Base` class using `declarative_base()`. This class will be used as the base class for defining database models.
|
@ -1,4 +1,5 @@
|
||||
Here's the `comments.py` file for the `app/api/v1/models/` directory in the `blog_app_igblf` FastAPI backend:
|
||||
Here's the `comments.py` file with a SQLAlchemy model for comments:
|
||||
|
||||
|
||||
from sqlalchemy import Column, ForeignKey, Integer, String, Text
|
||||
from sqlalchemy.orm import relationship
|
||||
@ -9,24 +10,16 @@ class Comment(Base):
|
||||
__tablename__ = "comments"
|
||||
|
||||
id = Column(Integer, primary_key=True, index=True)
|
||||
text = Column(Text, nullable=False)
|
||||
user_id = Column(Integer, ForeignKey("users.id"), nullable=False)
|
||||
content = Column(Text, nullable=False)
|
||||
author = Column(String(100), nullable=False)
|
||||
post_id = Column(Integer, ForeignKey("posts.id"), nullable=False)
|
||||
|
||||
user = relationship("User", back_populates="comments")
|
||||
post = relationship("Post", back_populates="comments")
|
||||
|
||||
def __repr__(self):
|
||||
return f"Comment(id={self.id}, text='{self.text[:20]}...', user_id={self.user_id}, post_id={self.post_id})"
|
||||
return f"Comment(id={self.id}, author='{self.author}', content='{self.content[:20]}...')"
|
||||
|
||||
Explanation:
|
||||
|
||||
1. We import the necessary modules from SQLAlchemy: `Column`, `ForeignKey`, `Integer`, `String`, `Text`, and `relationship`.
|
||||
5. We define the columns for the `Comment` model:
|
||||
- `id`: an integer primary key and index column.
|
||||
- `text`: a text column for the comment content, which is required (`nullable=False`).
|
||||
- `user_id`: an integer foreign key column referring to the `users` table, which is required (`nullable=False`).
|
||||
- `post_id`: an integer foreign key column referring to the `posts` table, which is required (`nullable=False`).
|
||||
6. We define the relationships between the `Comment` model and the `User` and `Post` models using the `relationship` function from SQLAlchemy:
|
||||
- `user`: a one-to-many relationship with the `User` model, using the `back_populates` parameter to enable bi-directional access.
|
||||
- `post`: a one-to-many relationship with the `Post` model, using the `back_populates` parameter to enable bi-directional access.
|
||||
|
||||
Note: This code assumes that you have already defined the `Post` model in a separate file, and that the necessary imports and database setup are handled elsewhere in your FastAPI project.
|
@ -1,10 +1,8 @@
|
||||
Here's the `posts.py` file for the `app/api/v1/models/` directory in the `blog_app_igblf` FastAPI backend project, defining a SQLAlchemy model for posts:
|
||||
Here's the `posts.py` file for the `blog_app` FastAPI backend, defining a SQLAlchemy model for posts:
|
||||
|
||||
|
||||
from sqlalchemy import Column, Integer, String, Text, ForeignKey
|
||||
from sqlalchemy import Column, ForeignKey, Integer, String, Text
|
||||
from sqlalchemy.orm import relationship
|
||||
from sqlalchemy.sql.sqltypes import TIMESTAMP
|
||||
from sqlalchemy.sql import func
|
||||
|
||||
from app.db import Base
|
||||
|
||||
@ -14,24 +12,13 @@ class Post(Base):
|
||||
id = Column(Integer, primary_key=True, index=True)
|
||||
title = Column(String, nullable=False)
|
||||
content = Column(Text, nullable=False)
|
||||
created_at = Column(TIMESTAMP, server_default=func.now())
|
||||
updated_at = Column(TIMESTAMP, server_default=func.now(), onupdate=func.now())
|
||||
user_id = Column(Integer, ForeignKey("users.id"), nullable=False)
|
||||
|
||||
user = relationship("User", back_populates="posts")
|
||||
author = relationship("User", back_populates="posts")
|
||||
|
||||
def __repr__(self):
|
||||
return f"Post(id={self.id}, title='{self.title}', content='{self.content[:20]}...')"
|
||||
|
||||
Explanation:
|
||||
This code defines a `Post` model that inherits from the `Base` class provided by SQLAlchemy. The `Post` model has the following fields:
|
||||
|
||||
3. The following columns are defined for the `Post` model:
|
||||
- `id`: An auto-incrementing primary key column of type `Integer`.
|
||||
- `title`: A non-nullable `String` column for the post title.
|
||||
- `content`: A non-nullable `Text` column for the post content.
|
||||
- `created_at`: A `TIMESTAMP` column that defaults to the current time when a new row is inserted.
|
||||
- `updated_at`: A `TIMESTAMP` column that defaults to the current time when a new row is inserted and updates to the current time whenever the row is updated.
|
||||
- `user_id`: A non-nullable `Integer` column that acts as a foreign key referencing the `id` column of the `users` table.
|
||||
4. The `user` attribute is defined as a SQLAlchemy relationship to the `User` model, which is assumed to be defined in another file (e.g., `app/api/v1/models/users.py`). The `back_populates` parameter specifies the name of the attribute on the `User` model that should be used for the reverse relationship.
|
||||
|
||||
Note: This code assumes that you have already set up the necessary database connection and defined the `Base` class in the `app/db.py` file. Additionally, you'll need to create the `users` table and define the `User` model in a separate file (e.g., `app/api/v1/models/users.py`) to establish the relationship between posts and users.
|
||||
- `user_id`: An integer foreign key referencing the `id` of the `User` model (assuming it exists).
|
@ -1,22 +1,25 @@
|
||||
Here's the `tags.py` file that defines a SQLAlchemy model for tags, located in the `app/api/v1/models/` directory:
|
||||
Here's the `tags.py` file for the `app/api/v1/models/` directory in the `blog_app_igblf` FastAPI backend:
|
||||
|
||||
from sqlalchemy import Column, Integer, String
|
||||
from app.db import Base
|
||||
from app.db.base_class import Base
|
||||
|
||||
class Tag(Base):
|
||||
__tablename__ = "tags"
|
||||
|
||||
id = Column(Integer, primary_key=True, index=True)
|
||||
name = Column(String, unique=True, index=True)
|
||||
name = Column(String, index=True)
|
||||
slug = Column(String, index=True, unique=True)
|
||||
|
||||
def __repr__(self):
|
||||
return f"Tag(id={self.id}, name='{self.name}')"
|
||||
return f"Tag(id={self.id}, name='{self.name}', slug='{self.slug}')"
|
||||
|
||||
Explanation:
|
||||
|
||||
1. We import the necessary modules from SQLAlchemy: `Column`, `Integer`, and `String`.
|
||||
5. We define three columns for the `Tag` model:
|
||||
- `id`: An integer primary key column with an index.
|
||||
- `name`: A string column with an index.
|
||||
- `slug`: A unique string column with an index.
|
||||
|
||||
|
||||
The `Tag` model has the following attributes:
|
||||
|
||||
|
||||
|
||||
This file assumes that you have already set up the necessary imports and dependencies for SQLAlchemy and the database connection in your FastAPI project. If you haven't done so, you'll need to add the required imports and configurations in the appropriate files (e.g., `app/db.py`, `app/main.py`).
|
||||
|
||||
Additionally, you'll need to create the `tags` table in your SQLite database using the `Base.metadata.create_all(engine)` method, where `engine` is the database engine instance you've configured in your project.
|
||||
Note: Make sure to adjust the import paths (`app.db.base_class`) according to your project's structure and naming conventions.
|
@ -1,25 +1,29 @@
|
||||
Here's the `user.py` file for the `app/api/v1/models/` directory in the `blog_app_igblf` FastAPI backend:
|
||||
Here's the `user.py` file for the `app/api/v1/models/` directory of the `blog_app_igblf` FastAPI backend, defining a SQLAlchemy model for the `User` entity:
|
||||
|
||||
|
||||
from sqlalchemy import Column, Integer, String, Boolean
|
||||
from app.db import Base
|
||||
from sqlalchemy.orm import relationship
|
||||
|
||||
from app.db.base_class 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)
|
||||
hashed_password = Column(String)
|
||||
email = Column(String, unique=True, index=True, nullable=False)
|
||||
username = Column(String, unique=True, index=True, nullable=False)
|
||||
hashed_password = Column(String, nullable=False)
|
||||
is_active = Column(Boolean, default=True)
|
||||
is_superuser = Column(Boolean, default=False)
|
||||
|
||||
posts = relationship("Post", back_populates="author")
|
||||
|
||||
def __repr__(self):
|
||||
return f"User(id={self.id}, username='{self.username}', email='{self.email}')"
|
||||
return f"User(id={self.id}, email='{self.email}', username='{self.username}')"
|
||||
|
||||
This file defines a SQLAlchemy model named `User` that inherits from the `Base` class (which should be defined in `app/db.py`). The `User` model has the following columns:
|
||||
This file defines a `User` model with the following fields:
|
||||
|
||||
- `is_active`: A boolean indicating whether the user is active or not (default is `True`).
|
||||
- `is_superuser`: A boolean indicating whether the user is a superuser or not (default is `False`).
|
||||
- `is_active` (Boolean, default=True)
|
||||
- `is_superuser` (Boolean, default=False)
|
||||
|
||||
|
||||
Make sure to import the necessary modules (`sqlalchemy` and `app.db`) at the top of the file. Also, ensure that the `Base` class is properly defined in `app/db.py` and that the SQLite database is correctly configured and initialized in your FastAPI application.
|
||||
The `User` model also has a one-to-many relationship with the `Post` model (not defined here), where each user can have multiple posts.
|
@ -1,22 +1,30 @@
|
||||
Here's the `__init__.py` file for the `app/api/v1/routes/` directory, which aggregates the routers for posts, comments, tags, and user:
|
||||
Here's the `__init__.py` file for the `app/api/v1/routes/` directory, which aggregates the routers for posts, comments, tags, and users in the `blog_app_igblf` FastAPI backend:
|
||||
|
||||
from fastapi import APIRouter
|
||||
|
||||
from .posts import router as posts_router
|
||||
from .comments import router as comments_router
|
||||
from .tags import router as tags_router
|
||||
from .user import router as user_router
|
||||
from app.api.v1.routes.posts import router as posts_router
|
||||
from app.api.v1.routes.comments import router as comments_router
|
||||
from app.api.v1.routes.tags import router as tags_router
|
||||
from app.api.v1.routes.users import router as users_router
|
||||
|
||||
router = APIRouter()
|
||||
|
||||
router.include_router(posts_router, prefix="/posts", tags=["posts"])
|
||||
router.include_router(comments_router, prefix="/comments", tags=["comments"])
|
||||
router.include_router(tags_router, prefix="/tags", tags=["tags"])
|
||||
router.include_router(user_router, prefix="/user", tags=["user"])
|
||||
router.include_router(users_router, prefix="/users", tags=["users"])
|
||||
|
||||
Explanation:
|
||||
This `__init__.py` file imports the routers for posts, comments, tags, and users from their respective modules (`app.api.v1.routes.posts`, `app.api.v1.routes.comments`, `app.api.v1.routes.tags`, and `app.api.v1.routes.users`). It then creates an instance of `APIRouter` and includes each of the imported routers with their respective prefixes and tags.
|
||||
|
||||
- `prefix` is used to define the base URL path for each router.
|
||||
- `tags` is used to group related routes in the automatically generated API documentation.
|
||||
|
||||
Note: Make sure that the `posts.py`, `comments.py`, `tags.py`, and `user.py` files exist in the same directory (`app/api/v1/routes/`) and contain the respective router definitions.
|
||||
|
||||
By including all the routers in this `__init__.py` file, you can easily mount the combined router in your FastAPI application. For example, in your `main.py` file, you can import this combined router and include it like this:
|
||||
|
||||
from fastapi import FastAPI
|
||||
from app.api.v1.routes import router as api_router
|
||||
|
||||
app = FastAPI()
|
||||
app.include_router(api_router, prefix="/api/v1")
|
||||
|
||||
|
||||
Note: This code assumes that you have separate modules for each of the routers (`app.api.v1.routes.posts`, `app.api.v1.routes.comments`, `app.api.v1.routes.tags`, and `app.api.v1.routes.users`) and that they have been properly defined and imported.
|
@ -1,14 +1,16 @@
|
||||
Here's the `comments.py` file with CRUD endpoints for comments:
|
||||
|
||||
from typing import List
|
||||
from fastapi import APIRouter, Depends, HTTPException
|
||||
from sqlalchemy.orm import Session
|
||||
|
||||
from app.db import get_db
|
||||
from app.db.session import get_db
|
||||
from app.models.comment import Comment
|
||||
from app.schemas.comment import CommentCreate, CommentResponse
|
||||
|
||||
router = APIRouter()
|
||||
|
||||
@router.post("/comments", response_model=CommentResponse, status_code=201)
|
||||
@router.post("/comments/", response_model=CommentResponse)
|
||||
def create_comment(comment: CommentCreate, db: Session = Depends(get_db)):
|
||||
db_comment = Comment(**comment.dict())
|
||||
db.add(db_comment)
|
||||
@ -16,17 +18,17 @@ def create_comment(comment: CommentCreate, db: Session = Depends(get_db)):
|
||||
db.refresh(db_comment)
|
||||
return db_comment
|
||||
|
||||
@router.get("/comments", response_model=List[CommentResponse])
|
||||
def get_all_comments(db: Session = Depends(get_db)):
|
||||
@router.get("/comments/", response_model=List[CommentResponse])
|
||||
def read_comments(db: Session = Depends(get_db)):
|
||||
comments = db.query(Comment).all()
|
||||
return comments
|
||||
|
||||
@router.get("/comments/{comment_id}", response_model=CommentResponse)
|
||||
def get_comment(comment_id: int, db: Session = Depends(get_db)):
|
||||
comment = db.query(Comment).filter(Comment.id == comment_id).first()
|
||||
if not comment:
|
||||
def read_comment(comment_id: int, db: Session = Depends(get_db)):
|
||||
db_comment = db.query(Comment).filter(Comment.id == comment_id).first()
|
||||
if not db_comment:
|
||||
raise HTTPException(status_code=404, detail="Comment not found")
|
||||
return comment
|
||||
return db_comment
|
||||
|
||||
@router.put("/comments/{comment_id}", response_model=CommentResponse)
|
||||
def update_comment(comment_id: int, comment: CommentCreate, db: Session = Depends(get_db)):
|
||||
@ -40,22 +42,17 @@ def update_comment(comment_id: int, comment: CommentCreate, db: Session = Depend
|
||||
db.refresh(db_comment)
|
||||
return db_comment
|
||||
|
||||
@router.delete("/comments/{comment_id}", status_code=204)
|
||||
@router.delete("/comments/{comment_id}", response_model=CommentResponse)
|
||||
def delete_comment(comment_id: int, db: Session = Depends(get_db)):
|
||||
comment = db.query(Comment).filter(Comment.id == comment_id).first()
|
||||
if not comment:
|
||||
db_comment = db.query(Comment).filter(Comment.id == comment_id).first()
|
||||
if not db_comment:
|
||||
raise HTTPException(status_code=404, detail="Comment not found")
|
||||
db.delete(comment)
|
||||
db.delete(db_comment)
|
||||
db.commit()
|
||||
return None
|
||||
return db_comment
|
||||
|
||||
This code defines a set of CRUD (Create, Read, Update, Delete) endpoints for comments in a FastAPI application. Here's a breakdown of the functionality:
|
||||
|
||||
1. `create_comment` endpoint: Accepts a `CommentCreate` Pydantic model and creates a new comment in the database.
|
||||
2. `get_all_comments` endpoint: Retrieves a list of all comments from the database.
|
||||
3. `get_comment` endpoint: Retrieves a single comment by its ID. If the comment is not found, it raises an `HTTPException` with a 404 status code.
|
||||
4. `update_comment` endpoint: Updates an existing comment by its ID. If the comment is not found, it raises an `HTTPException` with a 404 status code.
|
||||
5. `delete_comment` endpoint: Deletes a comment by its ID. If the comment is not found, it raises an `HTTPException` with a 404 status code.
|
||||
This file defines the following endpoints:
|
||||
|
||||
|
||||
Note: You will need to import the required models and schemas in your application and ensure that the database connection is properly configured.
|
||||
|
||||
Note: Make sure you have the appropriate models and schemas defined in `app/models/comment.py` and `app/schemas/comment.py`, respectively.
|
@ -1,14 +1,18 @@
|
||||
Here's the `posts.py` file with CRUD endpoints for posts:
|
||||
|
||||
from typing import List
|
||||
from fastapi import APIRouter, Depends, HTTPException, status
|
||||
from fastapi import APIRouter, Depends, HTTPException
|
||||
from sqlalchemy.orm import Session
|
||||
|
||||
from app.db import get_db
|
||||
from app.models import Post
|
||||
from app.schemas import PostCreate, PostResponse
|
||||
|
||||
router = APIRouter()
|
||||
router = APIRouter(
|
||||
prefix="/posts",
|
||||
tags=["posts"],
|
||||
|
||||
@router.post("/posts", response_model=PostResponse, status_code=status.HTTP_201_CREATED)
|
||||
@router.post("/", response_model=PostResponse, status_code=201)
|
||||
def create_post(post: PostCreate, db: Session = Depends(get_db)):
|
||||
new_post = Post(**post.dict())
|
||||
db.add(new_post)
|
||||
@ -16,43 +20,39 @@ def create_post(post: PostCreate, db: Session = Depends(get_db)):
|
||||
db.refresh(new_post)
|
||||
return new_post
|
||||
|
||||
@router.get("/posts", response_model=List[PostResponse])
|
||||
@router.get("/", response_model=List[PostResponse])
|
||||
def get_all_posts(db: Session = Depends(get_db)):
|
||||
posts = db.query(Post).all()
|
||||
return posts
|
||||
|
||||
@router.get("/posts/{post_id}", response_model=PostResponse)
|
||||
@router.get("/{post_id}", response_model=PostResponse)
|
||||
def get_post(post_id: int, db: Session = Depends(get_db)):
|
||||
post = db.query(Post).filter(Post.id == post_id).first()
|
||||
if not post:
|
||||
raise HTTPException(status_code=status.HTTP_404_NOT_FOUND, detail="Post not found")
|
||||
raise HTTPException(status_code=404, detail="Post not found")
|
||||
return post
|
||||
|
||||
@router.put("/posts/{post_id}", response_model=PostResponse)
|
||||
@router.put("/{post_id}", response_model=PostResponse)
|
||||
def update_post(post_id: int, post: PostCreate, db: Session = Depends(get_db)):
|
||||
db_post = db.query(Post).filter(Post.id == post_id).first()
|
||||
if not db_post:
|
||||
raise HTTPException(status_code=status.HTTP_404_NOT_FOUND, detail="Post not found")
|
||||
update_data = post.dict(exclude_unset=True)
|
||||
for key, value in update_data.items():
|
||||
setattr(db_post, key, value)
|
||||
raise HTTPException(status_code=404, detail="Post not found")
|
||||
for field, value in post.dict().items():
|
||||
setattr(db_post, field, value)
|
||||
db.commit()
|
||||
db.refresh(db_post)
|
||||
return db_post
|
||||
|
||||
@router.delete("/posts/{post_id}", status_code=status.HTTP_204_NO_CONTENT)
|
||||
@router.delete("/{post_id}", status_code=204)
|
||||
def delete_post(post_id: int, db: Session = Depends(get_db)):
|
||||
post = db.query(Post).filter(Post.id == post_id).first()
|
||||
if not post:
|
||||
raise HTTPException(status_code=status.HTTP_404_NOT_FOUND, detail="Post not found")
|
||||
raise HTTPException(status_code=404, detail="Post not found")
|
||||
db.delete(post)
|
||||
db.commit()
|
||||
return
|
||||
return None
|
||||
|
||||
This file defines the following endpoints:
|
||||
This file defines five routes for CRUD operations on posts:
|
||||
|
||||
|
||||
The endpoints use SQLAlchemy models (`Post`) and Pydantic schemas (`PostCreate`, `PostResponse`) for data validation and serialization. The `get_db` dependency function from `app.db` is used to get a database session.
|
||||
|
||||
|
||||
Note: You'll need to define the `Post` model in `app/models.py` and the `PostCreate` and `PostResponse` schemas in `app/schemas.py` for this code to work properly.
|
||||
Note that this code assumes the existence of the following components:
|
@ -1,3 +1,5 @@
|
||||
Here's an example `tags.py` file with CRUD endpoints for tags:
|
||||
|
||||
from typing import List
|
||||
from fastapi import APIRouter, Depends, HTTPException
|
||||
from sqlalchemy.orm import Session
|
||||
@ -50,8 +52,4 @@ def delete_tag(tag_id: int, db: Session = Depends(get_db)):
|
||||
db.commit()
|
||||
return None
|
||||
|
||||
This file defines the following endpoints:
|
||||
|
||||
|
||||
|
||||
Note that you'll need to import the required models and schemas in this file, and define them in their respective modules (`app/models/tag.py` and `app/schemas/tag.py`).
|
||||
This file defines the following endpoints:
|
@ -1,55 +1,58 @@
|
||||
Here's the `user.py` file with CRUD endpoints for the `User` model:
|
||||
|
||||
Here's an example `user.py` file with CRUD endpoints for the `User` model in the `app/api/v1/routes/` directory for the `blog_app` FastAPI backend:
|
||||
|
||||
from typing import List
|
||||
from fastapi import APIRouter, Depends, HTTPException
|
||||
from sqlalchemy.orm import Session
|
||||
|
||||
from app.db import get_db
|
||||
from app.models import User as UserModel
|
||||
from app.schemas import User, UserCreate, UserUpdate
|
||||
from app.core import deps
|
||||
from app.schemas.user import UserCreate, UserUpdate, User
|
||||
from app.models.user import User as UserModel
|
||||
|
||||
router = APIRouter()
|
||||
|
||||
@router.get("/users/", response_model=List[User])
|
||||
def read_users(db: Session = Depends(get_db)):
|
||||
@router.post("/users", response_model=User, status_code=201)
|
||||
def create_user(user_in: UserCreate, db: Session = Depends(deps.get_db)):
|
||||
user = UserModel(**user_in.dict())
|
||||
db.add(user)
|
||||
db.commit()
|
||||
db.refresh(user)
|
||||
return user
|
||||
|
||||
@router.get("/users", response_model=List[User])
|
||||
def read_users(db: Session = Depends(deps.get_db)):
|
||||
users = db.query(UserModel).all()
|
||||
return users
|
||||
|
||||
@router.get("/users/{user_id}", response_model=User)
|
||||
def read_user(user_id: int, db: Session = Depends(get_db)):
|
||||
def read_user(user_id: int, db: Session = Depends(deps.get_db)):
|
||||
user = db.query(UserModel).get(user_id)
|
||||
if not user:
|
||||
raise HTTPException(status_code=404, detail="User not found")
|
||||
return user
|
||||
|
||||
@router.post("/users/", response_model=User)
|
||||
def create_user(user: UserCreate, db: Session = Depends(get_db)):
|
||||
db_user = UserModel(**user.dict())
|
||||
db.add(db_user)
|
||||
db.commit()
|
||||
db.refresh(db_user)
|
||||
return db_user
|
||||
|
||||
@router.put("/users/{user_id}", response_model=User)
|
||||
def update_user(user_id: int, user: UserUpdate, db: Session = Depends(get_db)):
|
||||
db_user = db.query(UserModel).get(user_id)
|
||||
if not db_user:
|
||||
def update_user(user_id: int, user_in: UserUpdate, db: Session = Depends(deps.get_db)):
|
||||
user = db.query(UserModel).get(user_id)
|
||||
if not user:
|
||||
raise HTTPException(status_code=404, detail="User not found")
|
||||
update_data = user.dict(exclude_unset=True)
|
||||
for key, value in update_data.items():
|
||||
setattr(db_user, key, value)
|
||||
update_data = user_in.dict(exclude_unset=True)
|
||||
for field, value in update_data.items():
|
||||
setattr(user, field, value)
|
||||
db.add(user)
|
||||
db.commit()
|
||||
db.refresh(db_user)
|
||||
return db_user
|
||||
db.refresh(user)
|
||||
return user
|
||||
|
||||
@router.delete("/users/{user_id}")
|
||||
def delete_user(user_id: int, db: Session = Depends(get_db)):
|
||||
db_user = db.query(UserModel).get(user_id)
|
||||
if not db_user:
|
||||
@router.delete("/users/{user_id}", status_code=204)
|
||||
def delete_user(user_id: int, db: Session = Depends(deps.get_db)):
|
||||
user = db.query(UserModel).get(user_id)
|
||||
if not user:
|
||||
raise HTTPException(status_code=404, detail="User not found")
|
||||
db.delete(db_user)
|
||||
db.delete(user)
|
||||
db.commit()
|
||||
return {"message": "User deleted successfully"}
|
||||
return None
|
||||
|
||||
This file defines the following endpoints:
|
||||
This code defines CRUD (Create, Read, Update, Delete) endpoints for the `User` model using the FastAPI router. Here's a breakdown of the code:
|
||||
|
||||
|
||||
Note that this code assumes the existence of the following components:
|
@ -1,13 +1,11 @@
|
||||
Here's the `comments.py` file with Pydantic schemas for comments, following the FastAPI project structure with SQLite and SQLAlchemy:
|
||||
Here's the `comments.py` file with Pydantic schemas for comments, to be placed in the `app/api/v1/schemas/` directory:
|
||||
|
||||
|
||||
from datetime import datetime
|
||||
from typing import Optional
|
||||
|
||||
from pydantic import BaseModel, Field
|
||||
from pydantic import BaseModel
|
||||
from datetime import datetime
|
||||
|
||||
class CommentBase(BaseModel):
|
||||
content: str = Field(..., min_length=1, max_length=500)
|
||||
content: str
|
||||
|
||||
class CommentCreate(CommentBase):
|
||||
pass
|
||||
@ -30,11 +28,11 @@ class Comment(CommentInDBBase):
|
||||
class CommentInDB(CommentInDBBase):
|
||||
pass
|
||||
|
||||
Explanation:
|
||||
Here's a breakdown of the file:
|
||||
|
||||
1. We import the necessary modules: `datetime` for working with dates and times, `typing` for type hints, and `pydantic` for defining data models.
|
||||
1. We import the necessary modules: `typing` for type hints, `pydantic` for defining data models, and `datetime` for working with date and time objects.
|
||||
|
||||
|
||||
|
||||
|
||||
5. `CommentInDBBase` inherits from `CommentBase` and adds additional fields for database-related information: `id` (comment ID), `post_id` (ID of the associated post), `created_at` (creation timestamp), and `updated_at` (optional update timestamp). The `Config` class is used to enable the `orm_mode`, which allows Pydantic to work with SQLAlchemy models.
|
||||
5. `CommentInDBBase` inherits from `CommentBase` and adds fields for the comment's ID (`id`), the associated post ID (`post_id`), the creation timestamp (`created_at`), and an optional update timestamp (`updated_at`). The `Config` class is used to enable the `orm_mode` for compatibility with SQLAlchemy models.
|
@ -1,10 +1,13 @@
|
||||
from typing import Optional
|
||||
from pydantic import BaseModel
|
||||
Here's the `posts.py` file with Pydantic schemas for posts, to be placed in the `app/api/v1/schemas/` directory:
|
||||
|
||||
from datetime import datetime
|
||||
from typing import Optional
|
||||
|
||||
from pydantic import BaseModel, Field
|
||||
|
||||
class PostBase(BaseModel):
|
||||
title: str
|
||||
content: str
|
||||
title: str = Field(..., min_length=3, max_length=100)
|
||||
content: str = Field(..., min_length=10)
|
||||
|
||||
class PostCreate(PostBase):
|
||||
pass
|
||||
@ -23,20 +26,12 @@ class PostInDBBase(PostBase):
|
||||
class Post(PostInDBBase):
|
||||
pass
|
||||
|
||||
class PostList(BaseModel):
|
||||
__root__: list[Post]
|
||||
class PostInDB(PostInDBBase):
|
||||
pass
|
||||
|
||||
Explanation:
|
||||
|
||||
1. We import the necessary modules: `typing` for type hints, `pydantic` for defining data models, and `datetime` for handling date and time.
|
||||
|
||||
2. `PostBase` is a base Pydantic model that defines the common fields for a post: `title` and `content`.
|
||||
This file defines the following Pydantic models:
|
||||
|
||||
|
||||
These models can be used in the FastAPI routes and services to validate and handle the data related to posts. They ensure data consistency and provide a clear separation between the different operations (create, update, read) on posts.
|
||||
|
||||
5. `PostInDBBase` inherits from `PostBase` and adds additional fields: `id` (post ID), `created_at` (creation timestamp), and `updated_at` (optional update timestamp). The `Config` class is set to `orm_mode = True` to allow Pydantic to work with SQLAlchemy models.
|
||||
|
||||
|
||||
|
||||
|
||||
Make sure to install the required dependencies (`pydantic` and `sqlalchemy`) in your project environment if you haven't already done so.
|
||||
Note: Make sure to import the necessary dependencies (`datetime`, `typing`, and `pydantic`) at the top of the file.
|
@ -1,5 +1,3 @@
|
||||
Here's the `tags.py` file with Pydantic schemas for tags, located in the `app/api/v1/schemas/` directory:
|
||||
|
||||
from typing import Optional
|
||||
from pydantic import BaseModel
|
||||
|
||||
@ -10,7 +8,7 @@ class TagCreate(TagBase):
|
||||
pass
|
||||
|
||||
class TagUpdate(TagBase):
|
||||
pass
|
||||
name: Optional[str] = None
|
||||
|
||||
class TagInDBBase(TagBase):
|
||||
id: int
|
||||
@ -27,4 +25,14 @@ class TagInDB(TagInDBBase):
|
||||
|
||||
Explanation:
|
||||
|
||||
1. We import the necessary modules: `typing` for type hints and `pydantic` for defining data models.
|
||||
1. We import the necessary modules: `typing` for type hints and `pydantic` for defining data models.
|
||||
|
||||
|
||||
|
||||
|
||||
5. `TagInDBBase` inherits from `TagBase` and adds an `id` field, representing the unique identifier of a tag in the database. It also sets `orm_mode = True` in the `Config` class, which allows Pydantic to read data from ORM objects.
|
||||
|
||||
|
||||
|
||||
|
||||
Note: Make sure to import and use these schemas in your FastAPI routes and services as needed.
|
@ -1,16 +1,15 @@
|
||||
Here's the `user.py` file with Pydantic schemas for the user model in the `app/api/v1/schemas/` directory:
|
||||
Sure, here's the `user.py` file for the `app/api/v1/schemas/` directory in the `blog_app_igblf` FastAPI backend project:
|
||||
|
||||
from typing import Optional
|
||||
from pydantic import BaseModel, EmailStr
|
||||
|
||||
class UserBase(BaseModel):
|
||||
email: Optional[EmailStr] = None
|
||||
email: EmailStr
|
||||
is_active: Optional[bool] = True
|
||||
is_superuser: bool = False
|
||||
full_name: Optional[str] = None
|
||||
|
||||
class UserCreate(UserBase):
|
||||
email: EmailStr
|
||||
password: str
|
||||
|
||||
class UserUpdate(UserBase):
|
||||
@ -28,9 +27,7 @@ class User(UserInDBBase):
|
||||
class UserInDB(UserInDBBase):
|
||||
hashed_password: str
|
||||
|
||||
Explanation:
|
||||
|
||||
1. We import the necessary modules: `typing` for type hints, and `pydantic` for defining data models.
|
||||
Here's a breakdown of the different schemas:
|
||||
|
||||
|
||||
|
||||
@ -39,4 +36,4 @@ Explanation:
|
||||
|
||||
|
||||
|
||||
Note: This file assumes that you have the necessary dependencies installed, such as `pydantic` and `email-validator` (for `EmailStr`). Additionally, you may need to adjust the import paths and model definitions based on your project's specific requirements and structure.
|
||||
Note: Make sure to import the necessary dependencies (`typing`, `pydantic`) at the top of the file.
|
38
main.py
38
main.py
@ -1,16 +1,22 @@
|
||||
Here's a `main.py` file for a FastAPI backend named 'blog_app' with necessary imports and middleware, including SQLite and SQLAlchemy support:
|
||||
|
||||
from fastapi import FastAPI
|
||||
import os
|
||||
from typing import List
|
||||
from fastapi import FastAPI, Depends, HTTPException, status
|
||||
from fastapi.middleware.cors import CORSMiddleware
|
||||
from sqlalchemy import create_engine
|
||||
from sqlalchemy.orm import sessionmaker, Session
|
||||
from sqlalchemy.ext.declarative import declarative_base
|
||||
from sqlalchemy.orm import sessionmaker
|
||||
|
||||
SQLALCHEMY_DATABASE_URL = "sqlite:///./blog_app.db"
|
||||
engine = create_engine(SQLALCHEMY_DATABASE_URL, connect_args={"check_same_thread": False})
|
||||
SessionLocal = sessionmaker(autocommit=False, autoflush=False, bind=engine)
|
||||
Base = declarative_base()
|
||||
|
||||
app = FastAPI()
|
||||
|
||||
origins = [
|
||||
"http://localhost",
|
||||
"http://localhost:8000",
|
||||
"http://localhost:3000",
|
||||
|
||||
app.add_middleware(
|
||||
@ -20,11 +26,6 @@ app.add_middleware(
|
||||
allow_methods=["*"],
|
||||
allow_headers=["*"],
|
||||
|
||||
SQLALCHEMY_DATABASE_URL = "sqlite:///./blog_app.db"
|
||||
engine = create_engine(SQLALCHEMY_DATABASE_URL, connect_args={"check_same_thread": False})
|
||||
SessionLocal = sessionmaker(autocommit=False, autoflush=False, bind=engine)
|
||||
Base = declarative_base()
|
||||
|
||||
def get_db():
|
||||
db = SessionLocal()
|
||||
try:
|
||||
@ -32,13 +33,22 @@ def get_db():
|
||||
finally:
|
||||
db.close()
|
||||
|
||||
from models import Base
|
||||
Base.metadata.create_all(bind=engine)
|
||||
|
||||
if __name__ == "__main__":
|
||||
import uvicorn
|
||||
uvicorn.run(app, host="0.0.0.0", port=8000)
|
||||
from routers import blog, user
|
||||
|
||||
This `main.py` file sets up the FastAPI application, configures CORS middleware, and establishes a connection to a SQLite database using SQLAlchemy. Here's a breakdown of the code:
|
||||
app.include_router(blog.router)
|
||||
app.include_router(user.router)
|
||||
|
||||
4. Define a dependency function `get_db()` to provide a database session for each request.
|
||||
@app.get("/")
|
||||
def root():
|
||||
return {"message": "Welcome to the Blog App!"}
|
||||
|
||||
Note: You'll need to install the required dependencies (`fastapi`, `uvicorn`, and `sqlalchemy`) before running this code. Additionally, you'll need to create your API routes, models, and other necessary components in separate files and import them as indicated in the placeholder comment.
|
||||
This `main.py` file sets up the necessary components for a FastAPI backend with SQLite and SQLAlchemy support. Here's a breakdown of what's included:
|
||||
|
||||
7. Creates database tables if they don't exist by calling `Base.metadata.create_all(bind=engine)`.
|
||||
8. Imports routers for blog and user functionality (assuming you have separate router files).
|
||||
10. Defines a root path (`/`) that returns a welcome message.
|
||||
|
||||
Note that this `main.py` file assumes you have separate files for models (`models.py`) and routers (`routers/blog.py` and `routers/user.py`). You'll need to create those files and define your models and routes accordingly.
|
@ -1,9 +1,17 @@
|
||||
Here's the `requirements.txt` file for the FastAPI backend named 'blog_app' with the specified dependencies:
|
||||
Here's the `requirements.txt` file for the `blog_app` FastAPI backend with the specified dependencies:
|
||||
|
||||
fastapi==0.92.0
|
||||
uvicorn==0.20.0
|
||||
sqlalchemy==1.4.46
|
||||
pydantic==1.10.4
|
||||
loguru==0.6.0
|
||||
|
||||
This file can be used to install the required dependencies for the 'blog_app' project. To install the dependencies, you can run the following command:
|
||||
This `requirements.txt` file includes the following dependencies:
|
||||
|
||||
- `fastapi==0.92.0`: The FastAPI web framework.
|
||||
- `uvicorn==0.20.0`: The ASGI server used to run the FastAPI application.
|
||||
- `sqlalchemy==1.4.46`: The Python SQL toolkit and Object-Relational Mapping (ORM) library.
|
||||
- `pydantic==1.10.4`: Data validation and settings management using Python type annotations.
|
||||
- `loguru==0.6.0`: A library for logging in Python that is intended to be a more user-friendly and efficient alternative to the standard logging module.
|
||||
|
||||
This will install the following packages:
|
||||
|
||||
- **sqlalchemy**: A Python SQL toolkit and Object-Relational Mapping (ORM) library for working with databases.
|
||||
Note: The specific versions listed in this `requirements.txt` file may need to be updated to the latest versions based on your project requirements and compatibility with other dependencies.
|
Loading…
x
Reference in New Issue
Block a user