Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
9 changes: 9 additions & 0 deletions .env
Original file line number Diff line number Diff line change
@@ -0,0 +1,9 @@
db_username=postgres # default for windows
db_password= #give it the password used when installing postgres
db_hostname=localhost
db_port=5432
db_name=postgres #name it anything you want

secret_key= #give it a strong secret key
algorithm=HS256
access_token_expire_minutes=30
2 changes: 1 addition & 1 deletion .gitignore
Original file line number Diff line number Diff line change
Expand Up @@ -19,11 +19,11 @@ env
docs_build
site_build
venv
venv311
docs.zip
archive.zip
# alembic
alembic/versions/
.env
# vim temporary files
*~
.*.sw?
Expand Down
59 changes: 49 additions & 10 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -111,25 +111,29 @@ A simple Ecommerce API built with Fast API Framework

## Installation

1. **Clone the repository:**
1. **Install Python 3.11**
[Python 3.11 download link](https://www.python.org/downloads/release/python-3110/)


2. **Clone the repository:**

```bash
git clone https://github.com/aliseyedi01/Ecommerce-Api.git
```

2. **Navigate to the project directory:**
3. **Navigate to the project directory:**

```bash
Ecommerce-Api
```

3. **Create a virtual environment:**
4. **Create a virtual environment:**

```bash
python3 -m venv venv
python3.11 -m venv venv
```

4. **Activate the virtual environment:**
5. **Activate the virtual environment:**

On Windows:

Expand All @@ -143,39 +147,74 @@ A simple Ecommerce API built with Fast API Framework
source venv/bin/activate
```

5. **Install dependencies:**
6. **Install dependencies:**

```bash
pip install -r requirements.txt
```

7. **Install postgresql**



## Usage

1. **Run Alembic migrations:**
1. **Edit .env file**



2. **Run Alembic migrations:**

```bash
python migrate.py
```

if you got error create **versions** directory inside alembic folder.
This will apply any pending database migrations.

2. **Run the FastAPI development server:**
3. **Run the FastAPI development server:**

```bash
python run.py
```

The API will be accessible at [http://127.0.0.1:8000/](http://127.0.0.1:8000/)

3. **Access the Swagger UI and ReDoc:**
4. **Access the Swagger UI and ReDoc:**

- Swagger UI: [http://127.0.0.1:8000/docs/](http://127.0.0.1:8000/docs/)
- ReDoc: [http://127.0.0.1:8000/redoc/](http://127.0.0.1:8000/redoc/)

5. **First sign up using Swagger**

6. **Update the first user to admin**

connect to database like this :
```bash
psql -h localhost -U postgres -d postgres
```
with ``` \dt ``` you should see tables.
with
```sql
SELECT id, username, email, role FROM users;
```
you can see the user you created earlier. the role is user for default.
now we change the role to admin with :

```sql
UPDATE users
SET role = 'admin'
WHERE id = 1;
```
enter it line by line.(change your id if it's different)

**Congrats** now you have admin privilage.

to use swagger simply login with this user. then get the "access_token" from the login response.

use this token to Authorize.

now you aceess all the request types.



## Contributing
Expand Down
55 changes: 38 additions & 17 deletions alembic/env.py
Original file line number Diff line number Diff line change
Expand Up @@ -7,18 +7,23 @@
from app.core.config import settings
from app.db.database import Base

config = context.config
# IMPORT ALL MODELS - This is crucial for Alembic to detect them
from app.models.models import User, Cart, CartItem, Category, Product

config = context.config

config.set_main_option(
"sqlalchemy.url", f"postgresql://{settings.db_username}:{settings.db_password}@{settings.db_hostname}:{settings.db_port}/{settings.db_name}")


if config.config_file_name is not None:
fileConfig(config.config_file_name)

target_metadata = Base.metadata

# Debug: Print detected tables
print("=== TARGET METADATA DEBUG ===")
print(f"Tables to create: {list(target_metadata.tables.keys())}")
print("================================")

def run_migrations_offline() -> None:
url = config.get_main_option("sqlalchemy.url")
Expand All @@ -32,24 +37,40 @@ def run_migrations_offline() -> None:
with context.begin_transaction():
context.run_migrations()


def run_migrations_online() -> None:
connectable = engine_from_config(
config.get_section(config.config_ini_section, {}),
prefix="sqlalchemy.",
poolclass=pool.NullPool,
)

with connectable.connect() as connection:
context.configure(
connection=connection, target_metadata=target_metadata
print("=== STARTING MIGRATIONS ===")

# Debug: Print the connection URL (hide password)
url = config.get_main_option("sqlalchemy.url")
print(f"Database URL: {url.replace(':' + settings.db_password, ':****')}")

try:
connectable = engine_from_config(
config.get_section(config.config_ini_section, {}),
prefix="sqlalchemy.",
poolclass=pool.NullPool,
)

with context.begin_transaction():
context.run_migrations()

print("Database engine created successfully")

with connectable.connect() as connection:
print("Database connection established")

context.configure(
connection=connection, target_metadata=target_metadata
)

with context.begin_transaction():
print("Running migrations...")
context.run_migrations()
print("Migrations completed")

except Exception as e:
print(f"Migration error: {e}")
import traceback
traceback.print_exc()
raise

if context.is_offline_mode():
run_migrations_offline()
else:
run_migrations_online()
run_migrations_online()
50 changes: 48 additions & 2 deletions migrate.py
Original file line number Diff line number Diff line change
@@ -1,6 +1,52 @@
# migrate.py
import os
from alembic.config import Config
from alembic import command
from alembic.script import ScriptDirectory

alembic_cfg = Config("alembic.ini")
command.upgrade(alembic_cfg, "head")
def run_migrations():
# Load Alembic configuration
alembic_cfg = Config("alembic.ini")

# Get the script directory (where migration files are stored)
script = ScriptDirectory.from_config(alembic_cfg)

# Check if any migration files exist
versions_dir = script.versions
migration_files = [f for f in os.listdir(versions_dir) if f.endswith('.py') and f != '__pycache__']

print(f"Checking migrations in: {versions_dir}")
print(f"Found {len(migration_files)} migration files")

# If no migration files exist, create initial migration
if not migration_files:
print("No migration files found. Creating initial migration...")
try:
command.revision(alembic_cfg, autogenerate=True, message="Create initial tables")
print("✓ Initial migration created successfully")
except Exception as e:
print(f"✗ Error creating initial migration: {e}")
return False
else:
print("Migration files already exist:")
for file in migration_files:
print(f" - {file}")

# Run all pending migrations
print("Running migrations...")
try:
command.upgrade(alembic_cfg, "head")
print("✓ All migrations completed successfully")
return True
except Exception as e:
print(f"✗ Error running migrations: {e}")
return False

if __name__ == "__main__":
print("=== Database Migration Script ===")
success = run_migrations()
if success:
print("=== Migration process completed ===")
else:
print("=== Migration process failed ===")
exit(1)