This commit is contained in:
Felix Zett 2025-08-01 22:35:14 +02:00
commit 39f1470940
6 changed files with 116 additions and 0 deletions

11
backend/Dockerfile Normal file
View file

@ -0,0 +1,11 @@
FROM python:3.11-slim
WORKDIR /app
COPY requirements.txt .
RUN pip install --no-cache-dir -r requirements.txt
COPY . .
CMD ["uvicorn", "main:app", "--host", "0.0.0.0", "--port", "8000"]

8
backend/database.py Normal file
View file

@ -0,0 +1,8 @@
from sqlalchemy.ext.asyncio import create_async_engine, AsyncSession
from sqlalchemy.orm import sessionmaker
import os
DATABASE_URL = os.environ.get("DATABASE_URL")
engine = create_async_engine(DATABASE_URL, echo=True)
SessionLocal = sessionmaker(engine, class_=AsyncSession, expire_on_commit=False)

16
backend/main.py Normal file
View file

@ -0,0 +1,16 @@
from fastapi import FastAPI
from models import Base
from database import engine
app = FastAPI()
@app.on_event("startup")
async def startup():
async with engine.begin() as conn:
await conn.run_sync(Base.metadata.create_all)
@app.get("/")
def read_root():
return {"status": "running"}

51
backend/models.py Normal file
View file

@ -0,0 +1,51 @@
from sqlalchemy import Column, String, Boolean, Date, ForeignKey, Table, Text
from sqlalchemy.dialects.postgresql import UUID, ARRAY
from sqlalchemy.orm import relationship, declarative_base
import uuid
Base = declarative_base()
item_tags = Table(
"item_tags",
Base.metadata,
Column("item_id", UUID(as_uuid=True), ForeignKey("items.id")),
Column("tag_id", UUID(as_uuid=True), ForeignKey("tags.id")),
)
class Item(Base):
__tablename__ = "items"
id = Column(UUID(as_uuid=True), primary_key=True, default=uuid.uuid4)
user_id = Column(UUID(as_uuid=True), nullable=False)
name = Column(Text, nullable=False)
tags = relationship("Tag", secondary=item_tags, back_populates="items")
class Tag(Base):
__tablename__ = "tags"
id = Column(UUID(as_uuid=True), primary_key=True, default=uuid.uuid4)
user_id = Column(UUID(as_uuid=True), nullable=False)
name = Column(String, nullable=False, unique=False)
items = relationship("Item", secondary=item_tags, back_populates="tags")
class Trip(Base):
__tablename__ = "trips"
id = Column(UUID(as_uuid=True), primary_key=True, default=uuid.uuid4)
user_id = Column(UUID(as_uuid=True), nullable=False)
name = Column(String)
start_date = Column(Date)
end_date = Column(Date)
selected_tags = Column(ARRAY(String))
marked_tags = Column(ARRAY(String))
class TripItem(Base):
__tablename__ = "trip_items"
id = Column(UUID(as_uuid=True), primary_key=True, default=uuid.uuid4)
trip_id = Column(UUID(as_uuid=True), ForeignKey("trips.id"))
item_id = Column(UUID(as_uuid=True), ForeignKey("items.id"), nullable=True)
tag = Column(String, nullable=True) # e.g. "#kristin"
name = Column(Text)
calculated_label = Column(Text)
checked = Column(Boolean, default=False)

7
backend/requirements.txt Normal file
View file

@ -0,0 +1,7 @@
fastapi
uvicorn[standard]
sqlalchemy
asyncpg
pydantic
python-dotenv

23
docker-compose.yml Normal file
View file

@ -0,0 +1,23 @@
version: "3.9"
services:
backend:
build: ./backend
ports:
- "8000:8000"
volumes:
- ./backend:/app
environment:
- DATABASE_URL=postgresql+asyncpg://postgres:postgres@db:5432/packlist
db:
image: postgres:15
environment:
POSTGRES_USER: postgres
POSTGRES_PASSWORD: postgres
POSTGRES_DB: packlist
volumes:
- db_data:/var/lib/postgresql/data
volumes:
db_data: