diff --git a/app/api/core/dependencies/dependencies.py b/app/api/core/dependencies/dependencies.py new file mode 100644 index 0000000..361233a --- /dev/null +++ b/app/api/core/dependencies/dependencies.py @@ -0,0 +1,46 @@ +Here's the `dependencies.py` file for the specified location `app/api/core/dependencies/`: + +```python +from typing import Generator + +from sqlalchemy.orm import Session + +from app.api.db.database import SessionLocal + +def get_db() -> Generator[Session, None, None]: + """ + Dependency function that provides a SQLAlchemy session. + + Yields: + Session: A SQLAlchemy session instance. + """ + db = SessionLocal() + try: + yield db + finally: + db.close() +``` + +This file defines a `get_db` function that serves as a dependency for FastAPI routes that require a database session. The function uses the `SessionLocal` object from `app.api.db.database` to create a new SQLAlchemy session, which is then yielded to the requesting route. + +The `get_db` function is a generator function that yields the session instance and ensures it is properly closed after the requesting route has finished executing. + +To use this dependency in a FastAPI route, you can include it as a function parameter, and FastAPI will automatically resolve the dependency by calling the `get_db` function and providing the yielded session instance. For example: + +```python +from fastapi import APIRouter, Depends +from sqlalchemy.orm import Session + +from app.api.core.dependencies import get_db + +router = APIRouter() + +@router.get("/items") +def get_items(db: Session = Depends(get_db)): + # Use the provided db session to interact with the database + ... +``` + +In this example, the `get_items` route receives a `Session` instance as the `db` parameter, which is automatically provided by FastAPI by calling the `get_db` dependency function. + +Note that you'll need to configure the `SessionLocal` object in `app.api.db.database` to connect to your SQLite database using the appropriate connection string and engine configuration. \ No newline at end of file diff --git a/app/api/core/middleware/activity_tracker.py b/app/api/core/middleware/activity_tracker.py new file mode 100644 index 0000000..66f6386 --- /dev/null +++ b/app/api/core/middleware/activity_tracker.py @@ -0,0 +1,52 @@ +Here's the `activity_tracker.py` file with the `ActivityTrackerMiddleware` class that logs request method, URL, and processing time: + +```python +# app/api/core/middleware/activity_tracker.py + +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) + + try: + response = await call_next(request) + finally: + 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 the entry point for the middleware, which is called for every incoming request. + +Here's how the middleware works: + +1. The `dispatch` method is called with the incoming `Request` object and a `call_next` function. +2. The current time is recorded using `time.time()` to calculate the processing time later. +3. The request method and URL are extracted from the `Request` object. +4. The `call_next` function is called with the `Request` object, which passes the request to the next middleware or the application itself. The response from the application is stored in the `response` variable. +5. After the response is received, the processing time is calculated by subtracting the start time from the current time. +6. A log message is constructed with the request method, URL, and processing time, and printed to the console using `print`. +7. The `response` is returned to the caller. + +To use this middleware in your FastAPI application, you need to add it to the list of middleware in your `main.py` file: + +```python +# main.py +from fastapi import FastAPI +from app.api.core.middleware.activity_tracker import ActivityTrackerMiddleware + +app = FastAPI() +app.add_middleware(ActivityTrackerMiddleware) + +# ... other routes and configurations ... +``` + +With this middleware in place, every incoming request to your FastAPI application will be logged with its method, URL, and processing time. \ No newline at end of file diff --git a/app/api/db/database.py b/app/api/db/database.py new file mode 100644 index 0000000..9fb4c0c --- /dev/null +++ b/app/api/db/database.py @@ -0,0 +1,48 @@ +Here's the `database.py` file for your FastAPI backend named 'blog_app' with SQLite configuration using SQLAlchemy: + +```python +# app/api/db/database.py + +from sqlalchemy import create_engine +from sqlalchemy.ext.declarative import declarative_base +from sqlalchemy.orm import sessionmaker + +# SQLite database URL +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 file contains the following components: + +1. **SQLALCHEMY_DATABASE_URL**: The URL for the SQLite database file `blog_app.db`. +2. **engine**: The SQLAlchemy engine created using the `create_engine` function with the `SQLALCHEMY_DATABASE_URL` and a specific connection argument for SQLite (`check_same_thread=False`). +3. **SessionLocal**: A class that creates database sessions using the `sessionmaker` function. The `autocommit` and `autoflush` parameters are set to `False` for better control over transactions. +4. **Base**: A base class for defining SQLAlchemy models, created using the `declarative_base` function. + +You can import and use these components in your FastAPI application as follows: + +```python +# Import the required components +from app.api.db.database import SessionLocal, engine, Base + +# Create a database session +db = SessionLocal() + +# Use the session for database operations +# ... + +# Close the session +db.close() +``` + +Make sure to create the `app/api/db/` directory in your project structure before adding this file. \ No newline at end of file diff --git a/app/api/v1/models/and.py b/app/api/v1/models/and.py new file mode 100644 index 0000000..a126d4e --- /dev/null +++ b/app/api/v1/models/and.py @@ -0,0 +1,41 @@ +Here's the `and.py` file with the `And` model for the `blog_app` application: + +```python +# app/api/v1/models/and.py + +from sqlalchemy import Column, ForeignKey, Integer, String +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, nullable=False) + content = Column(String, nullable=False) + user_id = Column(Integer, ForeignKey("users.id"), nullable=False) + + author = relationship("User", back_populates="ands") + + def __repr__(self): + return f"And(id={self.id}, title='{self.title}', content='{self.content[:20]}...', user_id={self.user_id})" +``` + +Explanation: + +1. We import the necessary modules from SQLAlchemy: `Column`, `ForeignKey`, `Integer`, `String`, and `relationship`. +2. We import the `Base` class from `app.api.db.database`, which represents the base class for all SQLAlchemy models in this project. +3. We define the `And` class, which inherits from the `Base` class. +4. The `__tablename__` attribute specifies the name of the database table associated with this model. +5. We define the following columns for the `And` model: + - `id`: An integer primary key column with an index. + - `title`: A non-nullable string column for the and title. + - `content`: A non-nullable string column for the and content. + - `user_id`: A non-nullable integer column that represents a foreign key referencing the `users` table. +6. We define a relationship between the `And` model and the `User` model using the `relationship` function from SQLAlchemy. This relationship is named `author` and is back-populated with the `ands` attribute on the `User` model. +7. We define the `__repr__` method to provide a string representation of the `And` instance, which can be useful for debugging and logging purposes. + +This model assumes that there is a `User` model defined elsewhere in the project, and that the `users` table exists in the database. The `And` model represents a blog and or article, where each and is associated with a specific user (author). + +When you create instances of the `And` model and add them to the database session, SQLAlchemy will automatically handle the creation of the `ands` table in the database, as well as the management of the foreign key relationship with the `users` table. \ No newline at end of file diff --git a/app/api/v1/models/comments.py b/app/api/v1/models/comments.py new file mode 100644 index 0000000..5d2fc0c --- /dev/null +++ b/app/api/v1/models/comments.py @@ -0,0 +1,44 @@ +Here's the `comments.py` file with the `Comments` model for the `blog_app` app: + +```python +# app/api/v1/models/comments.py + +from sqlalchemy import Column, ForeignKey, Integer, String, Text +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) + post_id = Column(Integer, ForeignKey("posts.id"), nullable=False) + author_id = Column(Integer, ForeignKey("users.id"), nullable=False) + content = Column(Text, nullable=False) + created_at = Column(String, nullable=False) + updated_at = Column(String, nullable=True) + + post = relationship("Posts", back_populates="comments") + author = relationship("Users", back_populates="comments") + + def __repr__(self): + return f"Comment(id={self.id}, post_id={self.post_id}, author_id={self.author_id}, content='{self.content}', created_at='{self.created_at}', updated_at='{self.updated_at}')" +``` + +Explanation: + +1. We import the necessary modules from SQLAlchemy, including `Column`, `ForeignKey`, `Integer`, `String`, `Text`, and `relationship`. +2. We also import `Base` from `app.api.db.database`, which is assumed to be the base class for SQLAlchemy models in this project. +3. The `Comments` class inherits from `Base` and defines the following columns: + - `id`: Primary key and index for the table. + - `post_id`: Foreign key referencing the `id` column of the `posts` table. + - `author_id`: Foreign key referencing the `id` column of the `users` table. + - `content`: Text content of the comment. + - `created_at`: String representing the creation timestamp of the comment. + - `updated_at`: String representing the last update timestamp of the comment (nullable). +4. We define two relationships: + - `post`: A relationship with the `Posts` model, back-populating the `comments` attribute. + - `author`: A relationship with the `Users` model, back-populating the `comments` attribute. +5. The `__repr__` method is defined to provide a string representation of the `Comments` object. + +Note: This model assumes the existence of `Posts` and `Users` models, which should be defined in separate files. Additionally, the `app.api.db.database` module should provide the `Base` class, which is typically defined using the SQLAlchemy declarative base. \ No newline at end of file diff --git a/app/api/v1/models/posts.py b/app/api/v1/models/posts.py new file mode 100644 index 0000000..4547538 --- /dev/null +++ b/app/api/v1/models/posts.py @@ -0,0 +1,32 @@ +Here's the `posts.py` file with the `Posts` model for the `blog_app` application: + +```python +# app/api/v1/models/posts.py + +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") +``` + +This model defines the `Posts` table with the following fields: + +- `id`: An auto-incrementing primary key for the post. +- `title`: A non-nullable string field for the post title. +- `content`: A non-nullable text field for the post content. +- `author_id`: A non-nullable foreign key referencing the `id` of the `Users` table, representing the author of the post. + +The `author` field is a relationship to the `Users` model, which allows accessing the author information from a post object. The `back_populates` parameter ensures that the relationship is bi-directional, allowing access to the associated posts from a user object. + +Note that this model assumes the existence of a `Users` model, which should be defined in a separate file (e.g., `users.py`). The `Base` class is imported from `app.api.db.database`, which is a common pattern in FastAPI projects using SQLAlchemy and SQLite. + +Make sure to import any necessary modules (e.g., `sqlalchemy`) in your project and configure the database connection properly. \ No newline at end of file diff --git a/app/api/v1/models/user.py b/app/api/v1/models/user.py new file mode 100644 index 0000000..5563bf4 --- /dev/null +++ b/app/api/v1/models/user.py @@ -0,0 +1,40 @@ +Here's the `user.py` file with the `User` model for the `blog_app` app: + +```python +# app/api/v1/models/user.py + +from sqlalchemy import Column, Integer, String, Boolean +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(Boolean, default=True) + is_admin = Column(Boolean, default=False) + + def __repr__(self): + return f"User(id={self.id}, username='{self.username}', email='{self.email}', is_active={self.is_active}, is_admin={self.is_admin})" +``` + +Explanation: + +1. We import the necessary modules from SQLAlchemy: `Column`, `Integer`, `String`, and `Boolean`. +2. We import the `Base` class from `app.api.db.database`, which is the base class for all SQLAlchemy models in the project. +3. We define the `User` class, which inherits from `Base`. +4. We set the `__tablename__` attribute to `"users"`, which will be the name of the table in the database. +5. We define the following columns for the `User` model: + - `id`: An integer primary key and index column. + - `username`: A string column that is unique and indexed. + - `email`: A string column that is unique and indexed. + - `password`: A string column for storing the user's password. + - `is_active`: A boolean column that indicates whether the user account is active or not, defaulting to `True`. + - `is_admin`: A boolean column that indicates whether the user has admin privileges or not, defaulting to `False`. +6. We define the `__repr__` method to provide a string representation of the `User` object, which is useful for debugging and logging purposes. + +This `User` model can be used in the FastAPI backend to handle user authentication, registration, and other user-related operations in the `blog_app` app. + +Note: Make sure to import this model in the appropriate places and create the necessary database tables using Alembic migrations or other methods provided by SQLAlchemy. \ No newline at end of file diff --git a/app/api/v1/routes/__init__.py b/app/api/v1/routes/__init__.py index e69de29..c616cde 100644 --- a/app/api/v1/routes/__init__.py +++ b/app/api/v1/routes/__init__.py @@ -0,0 +1,27 @@ +Here's the `routes/__init__.py` file for the FastAPI backend: + +```python +from fastapi import APIRouter + +from .and import router as and_router +from .user import router as user_router +from .posts import router as posts_router +from .comments import router as comments_router + +api_router = APIRouter() + +api_router.include_router(and_router, prefix="/ands", tags=["ands"]) +api_router.include_router(user_router, prefix="/users", tags=["users"]) +api_router.include_router(posts_router, prefix="/posts", tags=["posts"]) +api_router.include_router(comments_router, prefix="/comments", tags=["comments"]) +``` + +This file creates a main `APIRouter` instance `api_router` and includes the routers from `and.py`, `user.py`, `posts.py`, and `comments.py` with their respective prefixes and tags. + +The prefixes are set to `/ands`, `/users`, `/posts`, and `/comments`, respectively, ensuring that the routes defined in each router file are accessible under the corresponding URL path. + +The tags are set to `["ands"]`, `["users"]`, `["posts"]`, and `["comments"]`, respectively. These tags are used for grouping and organizing the API endpoints in the interactive documentation (e.g., Swagger UI or ReDoc). + +Make sure to import the necessary router instances from the corresponding files (`and.py`, `user.py`, `posts.py`, and `comments.py`) and include them in the main `api_router` using the `include_router` method. + +This file should be placed in the `app/api/v1/routes/` directory, as specified in the project structure. \ No newline at end of file diff --git a/app/api/v1/routes/and.py b/app/api/v1/routes/and.py new file mode 100644 index 0000000..51c5dc1 --- /dev/null +++ b/app/api/v1/routes/and.py @@ -0,0 +1,43 @@ +Here's the `and.py` file for the `app/api/v1/routes/` directory with the specified endpoints: + +```python +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_db = And(**and_data.dict()) + db.add(and_db) + db.commit() + db.refresh(and_db) + return and_db + +@router.get("/ands/{id}", response_model=AndResponse) +def read_and(id: int, db: Session = Depends(get_db)): + and_db = db.query(And).get(id) + if not and_db: + raise HTTPException(status_code=404, detail="And not found") + return and_db +``` + +Explanation: + +1. We import the necessary modules and classes from FastAPI, SQLAlchemy, and the project's models and schemas. +2. We create an instance of `APIRouter` to define our routes. +3. The `read_ands` function handles the `GET /ands` endpoint. It uses the `get_db` dependency to obtain a database session, queries all `And` objects from the database, and returns them as a list of `AndResponse` objects. +4. The `create_and` function handles the `POST /ands` endpoint. It takes an `AndCreate` object as input, creates a new `And` object from the data, adds it to the database session, commits the changes, and returns the newly created `And` object as an `AndResponse`. +5. The `read_and` function handles the `GET /ands/{id}` endpoint. It takes an `id` parameter, queries the database for an `And` object with the given ID, and returns it as an `AndResponse`. If no `And` object is found, it raises an `HTTPException` with a 404 status code. + +Note: This code assumes that you have defined the `And` model in `app.api.v1.models.and` and the `AndCreate` and `AndResponse` schemas in `app.api.v1.schemas.and`. Additionally, the `get_db` dependency function should be defined in `app.api.core.dependencies.dependencies`. \ No newline at end of file diff --git a/app/api/v1/routes/comments.py b/app/api/v1/routes/comments.py new file mode 100644 index 0000000..e53333a --- /dev/null +++ b/app/api/v1/routes/comments.py @@ -0,0 +1,44 @@ +Here's the 'comments.py' router file with the specified endpoints: + +```python +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)): + comments = db.query(Comments).filter(Comments.id == id).first() + if not comments: + raise HTTPException(status_code=404, detail="Comments not found") + return comments +``` + +Explanation: + +1. We import the necessary modules and dependencies. +2. We create an instance of `APIRouter` for our comments routes. +3. The `read_commentss` function handles the `GET /commentss` endpoint. It fetches all comments from the database using `db.query(Comments).all()` and returns them as a list of `CommentsResponse` models. +4. The `create_comments` function handles the `POST /commentss` endpoint. It creates a new comments instance from the provided `CommentsCreate` schema, adds it to the database, commits the changes, and returns the newly created comments as a `CommentsResponse` model. +5. The `read_comments` function handles the `GET /commentss/{id}` endpoint. It fetches a comments by its ID using `db.query(Comments).filter(Comments.id == id).first()`. If the comments is not found, it raises an `HTTPException` with a 404 status code. Otherwise, it returns the comments as a `CommentsResponse` model. +6. All database operations are performed using the `get_db` dependency, which provides a database session. + +Note: This code assumes that you have defined the `Comments` model in `app.api.v1.models.comments` and the `CommentsCreate` and `CommentsResponse` schemas in `app.api.v1.schemas.comments`. \ No newline at end of file diff --git a/app/api/v1/routes/posts.py b/app/api/v1/routes/posts.py new file mode 100644 index 0000000..92941e5 --- /dev/null +++ b/app/api/v1/routes/posts.py @@ -0,0 +1,44 @@ +# app/api/v1/routes/posts.py + +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 get_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 get_posts(id: int, db: Session = Depends(get_db)): + db_posts = db.query(Posts).filter(Posts.id == id).first() + if not db_posts: + raise HTTPException(status_code=404, detail="Posts not found") + return db_posts +``` + +This code defines a FastAPI router with three endpoints: + +1. `GET /postss`: Lists all posts from the database. It uses the `Posts` model from `app.api.v1.models.posts` and returns a list of `PostsResponse` schemas from `app.api.v1.schemas.posts`. + +2. `POST /postss`: Creates a new post in the database. It accepts a `PostsCreate` schema from `app.api.v1.schemas.posts` as the request body, creates a new `Posts` model instance, adds it to the database, and returns the created `PostsResponse` schema. + +3. `GET /postss/{id}`: Retrieves a specific post by ID from the database. It uses the `Posts` model from `app.api.v1.models.posts` and returns a `PostsResponse` schema from `app.api.v1.schemas.posts`. If the post with the given ID is not found, it raises an `HTTPException` with a 404 status code. + +All the endpoints use the `get_db` dependency from `app.api.core.dependencies.dependencies` to obtain a database session. + +Note: This code assumes that the `Posts` model, `PostsCreate` schema, and `PostsResponse` schema exist in the specified locations. You may need to create or modify these files based on your project's requirements. \ No newline at end of file diff --git a/app/api/v1/routes/user.py b/app/api/v1/routes/user.py new file mode 100644 index 0000000..d4d41a4 --- /dev/null +++ b/app/api/v1/routes/user.py @@ -0,0 +1,44 @@ +Here's the `user.py` file for the specified routes: + +```python +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 read_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 read_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 +``` + +Explanation: + +1. We import the necessary modules and dependencies. +2. We create an instance of `APIRouter` to define the routes. +3. The `read_users` function handles the `GET /users` route. It fetches all users from the database using `db.query(User).all()` and returns them as a list of `UserResponse` models. +4. The `create_user` function handles the `POST /users` route. It takes a `UserCreate` model as input, creates a new `User` instance from the input data, adds it to the database session, commits the changes, and returns the newly created user as a `UserResponse` model. +5. The `read_user` function handles the `GET /users/{user_id}` route. It fetches a user from the database based on the provided `user_id`. If the user is not found, it raises an `HTTPException` with a 404 status code. Otherwise, it returns the user as a `UserResponse` model. +6. All routes use the `get_db` dependency to obtain a database session. + +Note: This code assumes that you have defined the `User` model in `app.api.v1.models.user` and the `UserCreate` and `UserResponse` schemas in `app.api.v1.schemas.user`. Additionally, the `get_db` dependency should be defined in `app.api.core.dependencies.dependencies`. \ No newline at end of file diff --git a/app/api/v1/schemas/and.py b/app/api/v1/schemas/and.py new file mode 100644 index 0000000..e9e8784 --- /dev/null +++ b/app/api/v1/schemas/and.py @@ -0,0 +1,36 @@ +Here's the `and.py` file with the `AndCreate` and `And` schemas for the `blog_app` application: + +```python +# app/api/v1/schemas/and.py + +from typing import Optional +from pydantic import BaseModel + +# AndBase schema +class AndBase(BaseModel): + name: str + description: Optional[str] = None + +# AndCreate schema for creating a new "and" instance +class AndCreate(AndBase): + pass + +# And schema for reading "and" instances +class And(AndBase): + id: int + name: str + description: Optional[str] = None + + class Config: + orm_mode = True +``` + +Explanation: + +1. We import the necessary modules: `typing` for type hints, and `pydantic` for defining data models. +2. `AndBase` is a base Pydantic model that defines the common fields for both `AndCreate` and `And` schemas. It has two fields: `name` (required) and `description` (optional). +3. `AndCreate` inherits from `AndBase` and represents the schema for creating a new "and" instance. It doesn't add any additional fields. +4. `And` inherits from `AndBase` and represents the schema for reading "and" instances. It adds an `id` field, which is typically the primary key in the database. +5. In the `And` model, we set `orm_mode = True` in the `Config` class. This allows Pydantic to work with ORM objects (e.g., SQLAlchemy models) and automatically convert them to Pydantic models. + +This file can be used in your FastAPI application to define request and response models for the "and" entity in the `blog_app` context. You can import these models in your API routes and use them for data validation, serialization, and deserialization. \ No newline at end of file diff --git a/app/api/v1/schemas/comments.py b/app/api/v1/schemas/comments.py new file mode 100644 index 0000000..660b558 --- /dev/null +++ b/app/api/v1/schemas/comments.py @@ -0,0 +1,41 @@ +Ensure all necessary imports and dependencies are included, maintaining consistency with a FastAPI project structure using SQLite and SQLAlchemy. + +Here's the 'comments.py' file with the requested schemas: + +```python +# app/api/v1/schemas/comments.py + +from typing import Optional +from pydantic import BaseModel +from datetime import datetime + +# CommentsCreate schema for creating a new comment +class CommentsCreate(BaseModel): + content: str + post_id: int + user_id: int + +# Comments schema for reading/returning comments +class Comments(BaseModel): + id: int + content: str + created_at: datetime + updated_at: Optional[datetime] = None + post_id: int + user_id: int + + class Config: + orm_mode = True +``` + +Explanation: + +1. The necessary imports are included: `typing` for type hints, `pydantic` for defining the schemas, and `datetime` for handling date and time fields. + +2. The `CommentsCreate` schema is defined with fields `content` (str), `post_id` (int), and `user_id` (int). This schema will be used for creating new comments. + +3. The `Comments` schema is defined with fields `id` (int), `content` (str), `created_at` (datetime), `updated_at` (Optional[datetime]), `post_id` (int), and `user_id` (int). This schema will be used for reading and returning comments. + +4. The `orm_mode = True` configuration is set in the `Comments` schema, which tells Pydantic to read data from SQLAlchemy ORM models. + +Note: This file assumes that the `comments` table in the database has columns corresponding to the defined fields in the schemas. If the table structure is different, the schemas should be adjusted accordingly. \ No newline at end of file diff --git a/app/api/v1/schemas/posts.py b/app/api/v1/schemas/posts.py new file mode 100644 index 0000000..9587006 --- /dev/null +++ b/app/api/v1/schemas/posts.py @@ -0,0 +1,41 @@ +Here's the `posts.py` file with the `PostsCreate` and `Posts` schemas for the `blog_app`: + +```python +# app/api/v1/schemas/posts.py + +from typing import Optional +from pydantic import BaseModel +from datetime import datetime + +class PostsCreate(BaseModel): + title: str + content: str + published: bool = False + +class Posts(BaseModel): + id: int + title: str + content: str + published: bool + created_at: datetime + updated_at: Optional[datetime] = None + + class Config: + orm_mode = True +``` + +Explanation: + +1. The `PostsCreate` schema defines the fields required for creating a new post. It includes `title`, `content`, and an optional `published` field with a default value of `False`. + +2. The `Posts` schema defines the fields for representing a post in the database. It includes `id`, `title`, `content`, `published`, `created_at`, and an optional `updated_at` field. + +3. The `orm_mode = True` is set in the `Config` class of the `Posts` schema to allow Pydantic to automatically convert data from ORM objects (e.g., SQLAlchemy models) to Pydantic models and vice versa. + +4. The `Optional` type from the `typing` module is used for the `updated_at` field, indicating that it can be `None`. + +5. The `datetime` type is imported from the `datetime` module to represent the `created_at` and `updated_at` fields. + +This file should be placed in the `app/api/v1/schemas/` directory, following the typical FastAPI project structure. + +Make sure to install the required dependencies (`pydantic` and `typing`) in your project environment if they are not installed already. \ No newline at end of file diff --git a/app/api/v1/schemas/user.py b/app/api/v1/schemas/user.py new file mode 100644 index 0000000..856f1c0 --- /dev/null +++ b/app/api/v1/schemas/user.py @@ -0,0 +1,45 @@ +Ensure all necessary imports and dependencies are included, maintaining consistency with a FastAPI project structure using SQLite and SQLAlchemy. + +Here's the `user.py` file for the `app/api/v1/schemas/` directory: + +```python +from typing import Optional +from pydantic import BaseModel, EmailStr + +# User Schema for Pydantic Model +class UserBase(BaseModel): + email: EmailStr + is_active: Optional[bool] = True + is_superuser: bool = False + full_name: Optional[str] = None + +# Properties to receive via API on creation +class UserCreate(UserBase): + email: EmailStr + password: str + +# Properties to receive via API on update +class UserUpdate(UserBase): + password: Optional[str] = None + +# Additional properties to return via API +class User(UserBase): + id: int + + class Config: + orm_mode = True +``` + +Explanation: + +1. The `UserBase` class defines the common properties shared by all user schemas, including `email`, `is_active`, `is_superuser`, and `full_name`. + +2. The `UserCreate` class inherits from `UserBase` and adds the `password` field, which is required when creating a new user. + +3. The `UserUpdate` class also inherits from `UserBase` and includes an optional `password` field for updating an existing user's password. + +4. The `User` class inherits from `UserBase` and adds an `id` field, which is typically the primary key in the database. It also includes the `orm_mode = True` configuration to allow Pydantic to work with SQLAlchemy models. + +5. The necessary imports are included at the top of the file, including `typing` for type annotations, `pydantic` for defining the schemas, and `EmailStr` for email validation. + +This file defines the Pydantic schemas for the user model in the `blog_app` application, following the FastAPI project structure and using SQLite and SQLAlchemy for database operations. \ No newline at end of file diff --git a/main.py b/main.py index dca5c44..6ba45fa 100644 --- a/main.py +++ b/main.py @@ -1,7 +1,66 @@ +import uvicorn from fastapi import FastAPI +from starlette.middleware.cors import CORSMiddleware -app = FastAPI(title="Generated Backend") +from app.api.v1.routes import router as v1_router +from app.api.core.middleware import activity_tracker +from app.core.config import settings +from app.db.base import Base +from app.db.session import engine -@app.get("/") -def read_root(): - return {"message": "Welcome to the generated backend"} \ No newline at end of file +app = FastAPI( + title=settings.PROJECT_NAME, + openapi_url=f"{settings.API_V1_STR}/openapi.json" +) + +# Set all CORS enabled origins +if settings.BACKEND_CORS_ORIGINS: + app.add_middleware( + CORSMiddleware, + allow_origins=[str(origin) for origin in settings.BACKEND_CORS_ORIGINS], + allow_credentials=True, + allow_methods=["*"], + allow_headers=["*"], + ) + +# Include activity tracker middleware +app.middleware("http")(activity_tracker) + +# Include v1 router +app.include_router(v1_router, prefix=settings.API_V1_STR) + +# Create database tables +Base.metadata.create_all(bind=engine) + +if __name__ == "__main__": + uvicorn.run(app, host="0.0.0.0", port=8000) +``` + +This `main.py` file sets up the FastAPI application for the `blog_app` project. Here's a breakdown of what it does: + +1. Import necessary modules and dependencies. +2. Create an instance of the `FastAPI` app with the project name and OpenAPI URL. +3. Set up CORS middleware to allow cross-origin requests from specified origins. +4. Include the `activity_tracker` middleware from `app.api.core.middleware`. +5. Include the `v1_router` from `app.api.v1.routes` under the `/v1` prefix. +6. Create database tables using SQLAlchemy's `Base.metadata.create_all` method, which connects to the SQLite database `blog_app.db` (assuming the database URL is configured correctly in `app.core.config`). +7. If the script is run directly (not imported as a module), start the Uvicorn server on `0.0.0.0:8000`. + +Note that this code assumes the following project structure: + +``` +app/ + api/ + v1/ + routes.py + core/ + middleware.py + core/ + config.py + db/ + base.py + session.py +main.py +``` + +You'll need to create these files and directories, and populate them with the necessary code for your application. Additionally, you'll need to install the required dependencies (e.g., `fastapi`, `uvicorn`, `sqlalchemy`) and configure the database URL in `app.core.config`. \ No newline at end of file diff --git a/requirements.txt b/requirements.txt index a70e8ac..5fa6b12 100644 --- a/requirements.txt +++ b/requirements.txt @@ -1,4 +1,8 @@ +Here's the `requirements.txt` file with the requested dependencies: + +``` fastapi uvicorn sqlalchemy -pydantic \ No newline at end of file +pydantic +``` \ No newline at end of file