From 4c741c765ea9c945b36bd0f0c3a09053c531ea25 Mon Sep 17 00:00:00 2001 From: raythurman2386 Date: Sat, 22 Feb 2025 19:37:52 -0600 Subject: [PATCH] Update README and manage.py for improved setup instructions Revise the README to recommend using Docker for development and clarify database management commands. Enhance manage.py with a new reset_db command to facilitate database resets using Alembic. Adjust Docker command to run the FastAPI application through manage.py. --- README.md | 139 ++++++++++++++++++++++----------------- backend/alembic/env.py | 39 ++++++----- backend/manage.py | 15 ++++- backend/requirements.txt | Bin 1830 -> 1882 bytes docker-compose.yml | 2 +- 5 files changed, 119 insertions(+), 76 deletions(-) diff --git a/README.md b/README.md index fe70017..45f5a0e 100644 --- a/README.md +++ b/README.md @@ -92,42 +92,71 @@ fastapi-react-starter/ ## Quick Start -### Development +### Using Docker (Recommended) + +1. Clone the repository: + ```bash + git clone https://github.com/raythurman2386/fastapi-react-starter.git + cd fastapi-react-starter + ``` + +2. Create environment files: + + Create `.env` file in the root directory: + ```env + # Database Configuration + DB_USER=postgres + DB_PASSWORD=postgres + DB_NAME=fastapi_db + ``` + +3. Start the application with Docker: + ```bash + docker compose up --build + ``` + + This will: + - Start PostgreSQL database + - Reset the database (drop and recreate with fresh migrations) + - Start the FastAPI backend at http://localhost:8000 + - Start the React frontend at http://localhost:5173 + + The Swagger docs will be available at http://localhost:8000/docs + +### Manual Setup (Alternative) 1. Backend Setup: - First, create a `.env` file in the backend directory: + a. Install PostgreSQL and create a database: + ```bash + # macOS with Homebrew + brew install postgresql + brew services start postgresql + + # Create database + createdb fastapi_db + ``` + + b. Create a `.env` file in the backend directory: ```env - # Database Configuration (PostgreSQL) - DB_NAME=your_db_name - DB_USER=your_db_user - DB_PASSWORD=your_password + # Database Configuration + DB_NAME=fastapi_db + DB_USER=postgres # your database user + DB_PASSWORD=postgres # your database password DB_HOST=localhost DB_PORT=5432 - - # JWT Configuration - JWT_SECRET_KEY=your-secret-key-for-production + CORS_ORIGINS=["http://localhost:5173"] + ENVIRONMENT=development ``` - If you don't set database credentials, it will fall back to SQLite. - - Then set up the Python environment: + c. Install Python dependencies and run migrations: ```bash cd backend - python -m venv venv - # On Windows: - .\venv\Scripts\activate - # On Unix: - source venv/bin/activate - pip install -r requirements.txt + python manage.py reset_db # This will reset the database and apply migrations uvicorn app.main:app --reload ``` - The backend will be available at http://localhost:8000 - - API documentation: http://localhost:8000/docs - - Alternative docs: http://localhost:8000/redoc - 2. Frontend Setup: ```bash cd frontend @@ -135,53 +164,45 @@ fastapi-react-starter/ npm run dev ``` - The frontend will be available at http://localhost:5173 +### Database Management -### Authentication System +The project includes several database management commands: -The template includes a complete JWT-based authentication system with the following features: - -- User registration with email and username -- Email-based login -- JWT token generation and validation -- Role-based access control (user, admin, moderator) -- Password reset functionality -- Email verification support (ready to implement) - -### Database Support +```bash +# Reset the database (drop, recreate, and apply migrations) +python manage.py reset_db -The template supports both SQLite and PostgreSQL: +# Generate new migrations +python manage.py makemigrations "description of changes" -1. **SQLite** (Default): - - No configuration needed - - Great for development and small projects - - Database file: `app.db` in the backend directory +# Apply pending migrations +python manage.py migrate -2. **PostgreSQL**: - - Production-ready, scalable database - - Async support with asyncpg - - Connection pooling and proper cleanup - - Configure through environment variables +# Check migration status +python manage.py db_status -To use PostgreSQL, set the database environment variables in `.env` and ensure PostgreSQL is running. +# Rollback last migration +python manage.py downgrade +``` -### Frontend Components +If you encounter database errors: +1. Stop all running services +2. Reset the database using `python manage.py reset_db` or through Docker with `docker compose up --build` +3. The database will be recreated with fresh tables -The template uses shadcn/ui, a collection of beautifully designed, accessible components: +### Troubleshooting -- Fully styled with Tailwind CSS -- Dark mode support -- TypeScript integration -- Customizable themes -- Accessible by default -- Easy to extend and modify +1. Backend Status shows "error": + - Ensure PostgreSQL is running + - Check database credentials in `.env` + - Try resetting the database using `python manage.py reset_db` + - Check backend logs for specific error messages -To add new shadcn/ui components: -```bash -cd frontend -npx shadcn-ui@latest add button -# Replace 'button' with any component name -``` +2. User Registration fails: + - Ensure the database is properly initialized + - Check if backend is running and accessible + - Verify CORS settings in backend `.env` + - Check browser console for specific error messages ## Contributing diff --git a/backend/alembic/env.py b/backend/alembic/env.py index efbca46..479eab0 100644 --- a/backend/alembic/env.py +++ b/backend/alembic/env.py @@ -1,49 +1,58 @@ import asyncio from alembic import context from logging.config import fileConfig -from sqlalchemy.ext.asyncio import AsyncEngine -from app.db import Base, engine, get_database_url, create_engine_with_retry - +from app.db import Base, get_database_url, create_engine_with_retry +# Load Alembic configuration and set up logging config = context.config fileConfig(config.config_file_name) +# Set the target metadata from your SQLAlchemy models target_metadata = Base.metadata -async def run_migrations_online(): - """Run migrations in 'online' mode with async support.""" +def run_migrations_online(): + """ + Run migrations in 'online' mode with async support. + This is a synchronous wrapper that runs async code internally. + """ connectable = create_engine_with_retry(get_database_url()) - async with connectable.connect() as connection: - await connection.run_sync(do_run_migrations) + # Define an async helper function to handle the connection and migration + async def do_run_migrations_async(): + async with connectable.connect() as connection: + await connection.run_sync(do_run_migrations) + + # Run the async function synchronously using asyncio.run + asyncio.run(do_run_migrations_async()) def do_run_migrations(connection): + """ + Configure and run migrations synchronously on the provided connection. + """ context.configure(connection=connection, target_metadata=target_metadata) with context.begin_transaction(): context.run_migrations() -asyncio.run(run_migrations_online()) - - -def run_migrations_offline() -> None: - """Run migrations in 'offline' mode.""" - +def run_migrations_offline(): + """ + Run migrations in 'offline' mode. + Generates SQL scripts without connecting to the database. + """ url = get_database_url() - context.configure( url=url, target_metadata=target_metadata, literal_binds=True, dialect_opts={"paramstyle": "named"}, ) - with context.begin_transaction(): context.run_migrations() +# Determine whether to run migrations in offline or online mode if context.is_offline_mode(): run_migrations_offline() else: diff --git a/backend/manage.py b/backend/manage.py index 1e9179f..6c8d8f1 100644 --- a/backend/manage.py +++ b/backend/manage.py @@ -1,15 +1,19 @@ import typer import subprocess import os +from sqlalchemy import create_engine +from app.config import get_settings +from app.db import engine, Base app = typer.Typer() +settings = get_settings() @app.command() def run(): """Run the FastAPI application.""" typer.echo("Starting FastAPI app...") - subprocess.run(["uvicorn", "main:app", "--host", "0.0.0.0", "--port", "8000", "--reload"]) + subprocess.run(["uvicorn", "app.main:app", "--host", "0.0.0.0", "--port", "8000", "--reload"]) @app.command() @@ -47,5 +51,14 @@ def format(): subprocess.run(["black", "."]) +@app.command() +def reset_db(): + """Drop and recreate all database tables using Alembic""" + typer.echo("Resetting database using Alembic...") + subprocess.run(["alembic", "downgrade", "base"]) + subprocess.run(["alembic", "upgrade", "head"]) + typer.echo("Database reset successfully.") + + if __name__ == "__main__": app() diff --git a/backend/requirements.txt b/backend/requirements.txt index ec6d552045b71c8a1ff9cdcbbc59a8542311b422..d3543b3b55cf24eb9692a93ed9e20fe3c62afb22 100644 GIT binary patch delta 57 zcmZ3+cZ+X>6Ps=!Lk>eC5GONaFr+f%GE_3?GL$luFk}M7iW%$}Y#9s~^cYMS41uK4 IWNWt90E46qJpcdz delta 11 Scmcb`w~TLt6Wio6wkH4^Qv`?r diff --git a/docker-compose.yml b/docker-compose.yml index c4365e3..a0a84ea 100644 --- a/docker-compose.yml +++ b/docker-compose.yml @@ -39,7 +39,7 @@ services: timeout: 5s retries: 5 start_period: 10s - command: bash -c "sleep 5 && uvicorn app.main:app --host 0.0.0.0 --port 8000 --reload" + command: bash -c "python manage.py run" frontend: build: