from fastapi import FastAPI from pydantic import BaseModel, Field, EmailStr from sqlalchemy import ( Column, Integer, String, DateTime, Enum, ForeignKey, Text, Float, Boolean, create_engine ) from sqlalchemy.orm import declarative_base, relationship, sessionmaker from sqlalchemy.dialects.postgresql import JSONB from enum import Enum as PyEnum import datetime app = FastAPI() Base = declarative_base() # Enums class Role(str, PyEnum): admin = "admin" user = "user" mod = "mod" class Status(str, PyEnum): active = "active" banned = "banned" suspended = "suspended" class ItemType(str, PyEnum): text = "text" image = "image" class VoteType(str, PyEnum): up = "up" down = "down" # SQLAlchemy Models class User(Base): __tablename__ = "users" user_id = Column(Integer, primary_key=True, index=True) username = Column(String, unique=True, nullable=False) name = Column(String) surname = Column(String) email = Column(String, unique=True, nullable=False) role = Column(Enum(Role), default=Role.user) status = Column(Enum(Status), default=Status.active) bio = Column(String(144)) created_date = Column(DateTime, default=datetime.datetime.utcnow) collections = relationship("Collection", back_populates="user") items = relationship("Item", back_populates="user") class Collection(Base): __tablename__ = "collections" collection_id = Column(Integer, primary_key=True) user_id = Column(Integer, ForeignKey("users.user_id")) visibility = Column(Boolean, default=True) # True = public, False = private collection_name = Column(String, nullable=False) collection_bio = Column(String) user = relationship("User", back_populates="collections") items = relationship("Item", back_populates="collection") class Item(Base): __tablename__ = "items" item_id = Column(Integer, primary_key=True) user_id = Column(Integer, ForeignKey("users.user_id")) date = Column(DateTime, default=datetime.datetime.utcnow) location_x = Column(Float) location_y = Column(Float) item_type = Column(Enum(ItemType)) content_text = Column(Text, nullable=True) content_image_path = Column(String, nullable=True) collection_id = Column(Integer, ForeignKey("collections.collection_id")) score = Column(Integer, default=0) user = relationship("User", back_populates="items") collection = relationship("Collection", back_populates="items") votes = relationship("Vote", back_populates="item") class Vote(Base): __tablename__ = "votes" vote_id = Column(Integer, primary_key=True) user_id = Column(Integer, ForeignKey("users.user_id")) item_id = Column(Integer, ForeignKey("items.item_id")) vote_type = Column(Enum(VoteType)) date = Column(DateTime, default=datetime.datetime.utcnow) item = relationship("Item", back_populates="votes") # Pydantic Schemas class UserCreate(BaseModel): username: str name: str surname: str email: EmailStr bio: str = Field(max_length=144) class ItemCreate(BaseModel): location_x: float location_y: float item_type: ItemType content_text: str | None = None content_image_path: str | None = None collection_id: int class CollectionCreate(BaseModel): collection_name: str collection_bio: str visibility: bool = True class VoteCreate(BaseModel): item_id: int vote_type: VoteType # DB Setup (edit with your DB credentials) DATABASE_URL = "postgresql://username:password@localhost:5432/mydatabase" engine = create_engine(DATABASE_URL) SessionLocal = sessionmaker(bind=engine) Base.metadata.create_all(bind=engine)