update models to use string type for id fields

This commit is contained in:
Thomas Peetz
2025-05-02 11:21:57 +02:00
parent 7ff2bf912d
commit c77adb0e04
31 changed files with 397 additions and 233 deletions
+6 -7
View File
@@ -1,11 +1,10 @@
from uuid import UUID
from typing import List
from typing import List, AnyStr
from fastapi import APIRouter, HTTPException, status
from sqlalchemy import select
from src.apis.utils import SessionDep
from src.db.repository.comic import get_artist_details, list_comics
from src.schema.comics.comic import ComicResponse, ComicDetailsResponse, get_comic_details, get_short_info
from src.schema.comics.artist import ArtistCreation, ArtistDetailResponse, ArtistResponse, get_artist_details
from src.schema.comics.artist import ArtistCreation, ArtistDetailResponse, ArtistResponse
from src.db.models.comic import Comic, Artist
router = APIRouter(
@@ -18,14 +17,14 @@ router = APIRouter(
@router.get("/comics")
def get_all_comics(db: SessionDep) -> List[ComicResponse]:
results: List[ComicResponse] = []
comics = db.scalars(select(Comic)).all()
comics = list_comics(db)
for comic in comics:
response = get_short_info(comic)
results.append(response)
return results
@router.get("/comics/{comic_id}", response_model=ComicDetailsResponse)
def get_comic(comic_id: UUID, db: SessionDep) -> ComicDetailsResponse:
def get_comic(comic_id: AnyStr, db: SessionDep) -> ComicDetailsResponse:
comic = db.get(Comic, comic_id)
if comic is None:
raise HTTPException(status_code=404, detail="Comic could not be found")
@@ -41,7 +40,7 @@ def get_all_artists(db: SessionDep) -> List[ArtistResponse]:
return results
@router.get("/artists/{artist_id}", response_model=ArtistDetailResponse)
def get_artist(artist_id: UUID, db: SessionDep) -> ArtistDetailResponse:
def get_artist(artist_id: AnyStr, db: SessionDep) -> ArtistDetailResponse:
artist = db.get(Artist, artist_id)
if artist is None:
raise HTTPException(status_code=404, detail="Artist could not be found")
+3 -3
View File
@@ -1,4 +1,4 @@
from typing import List
from typing import List, AnyStr
from uuid import UUID
from fastapi import APIRouter, status, HTTPException
@@ -42,7 +42,7 @@ def get_all_files(db: SessionDep, review: bool = False, download: bool = False)
return results
@router.get("/files/{file_id}", response_model=MediaFileResponse)
def get_file(file_id: UUID, db: SessionDep) -> MediaFileResponse:
def get_file(file_id: AnyStr, db: SessionDep) -> MediaFileResponse:
mediafile = db.get(MediaFile, file_id)
if not mediafile:
raise HTTPException(status_code=404, detail="MediaFile could not be found")
@@ -50,7 +50,7 @@ def get_file(file_id: UUID, db: SessionDep) -> MediaFileResponse:
return response
@router.put("/files/{file_id}", response_model=MediaFileResponse)
def update_file(file_id: UUID, db: SessionDep, info: MediaFileResponse) -> MediaFileResponse:
def update_file(file_id: AnyStr, db: SessionDep, info: MediaFileResponse) -> MediaFileResponse:
mediaFile = db.get(MediaFile, file_id)
if not mediaFile:
raise HTTPException(status_code=404, detail="MediaFile could not be found")
+14 -14
View File
@@ -8,11 +8,11 @@ from src.db.models.base import Base, BaseMixin
class Profile(Base, BaseMixin):
__tablename__ = 'profile'
first_name = Column(String(255))
last_name = Column(String(255))
user_name = Column(String(255), nullable=False)
email = Column(String(255))
password = Column(String(255))
first_name = Column(String)
last_name = Column(String)
user_name = Column(String, nullable=False)
email = Column(String)
password = Column(String)
enabled = Column(Boolean)
assignments = relationship("Assignment")
tokens = relationship("Token")
@@ -30,17 +30,17 @@ class Profile(Base, BaseMixin):
class Token(Base, BaseMixin):
__tablename__ = "token"
token = Column(String(255), nullable=False, unique=True)
name = Column(String(255))
token = Column(String, nullable=False, unique=True)
name = Column(String)
last_used_date: Mapped[datetime] = mapped_column()
enabled = Column(Boolean)
profile_id = Column(String(255), ForeignKey("profile.id"), nullable=False)
profile_id = Column(String, ForeignKey("profile.id"), nullable=False)
profile = relationship("Profile", back_populates="tokens")
class Permission(Base, BaseMixin):
__tablename__ = "permission"
name = Column(String(255), nullable=False)
name = Column(String, nullable=False)
assignments = relationship("Assignment")
@@ -54,17 +54,17 @@ class Assignment(Base, BaseMixin):
class ModuleData(Base, BaseMixin):
__tablename__ = "module_data"
module_name = Column(String(255), nullable=False)
module_name = Column(String, nullable=False)
import_data = Column(Boolean)
class MailAccount(Base, BaseMixin):
__tablename__ = "mail_account"
host = Column(String(255))
host = Column(String)
port = Column(Integer)
protocol = Column(String(255))
user_name = Column(String(255))
password = Column(String(255))
protocol = Column(String)
user_name = Column(String)
password = Column(String)
start_tls = Column(Boolean)
+7 -7
View File
@@ -10,8 +10,8 @@ class Base(DeclarativeBase):
class BaseMixin:
id = Column(String(255), primary_key=True, default=uuid.uuid4())
# id: Mapped[str] = mapped_column(primary_key=True, default=uuid.uuid4())
#id = Column(String(255), primary_key=True, default=uuid.uuid4)
id: Mapped[str] = mapped_column(primary_key=True, default=uuid.uuid4)
# created_date = Column(DateTime)
created_date: Mapped[datetime] = mapped_column(default=func.now())
# last_modified_date = Column(DateTime)
@@ -21,10 +21,10 @@ class BaseMixin:
class BaseVideoMixin:
cloud_link = Column(String(255))
file_name = Column(String(255))
path = Column(String(255))
cloud_link = Column(String)
file_name = Column(String)
path = Column(String)
review = Column(Boolean)
title = Column(String(255))
url = Column(String(255), unique=True)
title = Column(String)
url = Column(String, unique=True)
should_download = Column(Boolean)
+8 -8
View File
@@ -8,7 +8,7 @@ from src.db.models.base import Base, BaseMixin
class Publisher(Base, BaseMixin):
__tablename__ = "publisher"
name = Column(String(length=255), unique=True)
name = Column(String, unique=True)
comics = relationship("Comic")
def __repr__(self):
@@ -20,7 +20,7 @@ class Publisher(Base, BaseMixin):
class Comic(Base, BaseMixin):
__tablename__ = 'comic'
title = Column(String(length=255), unique=True)
title = Column(String, unique=True)
publisher_id = Column(String, ForeignKey('publisher.id'), nullable=False)
publisher = relationship("Publisher", back_populates="comics")
current_order = Column(Boolean)
@@ -55,7 +55,7 @@ class Comic(Base, BaseMixin):
class Volume(Base, BaseMixin):
__tablename__ = "volume"
name = Column(String(length=255), nullable=False)
name = Column(String, nullable=False)
comic_id = Column(String, ForeignKey("comic.id"), nullable=False)
comic = relationship("Comic", back_populates="volumes")
issues = relationship("Issue")
@@ -63,7 +63,7 @@ class Volume(Base, BaseMixin):
class TradePaperback(Base, BaseMixin):
__tablename__ = "trade_paperback"
name = Column(String(length=255), nullable=False)
name = Column(String, nullable=False)
issue_start = Column(Integer)
issue_end = Column(Integer)
comic_id = Column(String, ForeignKey("comic.id"), nullable=False)
@@ -72,14 +72,14 @@ class TradePaperback(Base, BaseMixin):
class StoryArc(Base, BaseMixin):
__tablename__ = "story_arc"
name = Column(String(length=255), nullable=False)
name = Column(String, nullable=False)
comic_id = Column(String, ForeignKey("comic.id"), nullable=False)
comic = relationship("Comic", back_populates="story_arcs")
class Issue(Base, BaseMixin):
__tablename__ = "issue"
issue_number = Column(String(255))
issue_number = Column(String)
in_stock = Column(Boolean)
is_read = Column(Boolean)
comic_id = Column(String, ForeignKey("comic.id"), nullable=False)
@@ -90,7 +90,7 @@ class Issue(Base, BaseMixin):
class Artist(Base, BaseMixin):
__tablename__ = "artist"
name = Column(String(length=255), nullable=False)
name = Column(String, nullable=False)
comic_works = relationship("ComicWork")
def get_comics(self) -> Dict[str, List[str]]:
@@ -107,7 +107,7 @@ class Artist(Base, BaseMixin):
class WorkType(Base, BaseMixin):
__tablename__ = "worktype"
name = Column(String(length=255), nullable=False, unique=True)
name = Column(String, nullable=False, unique=True)
comic_works = relationship("ComicWork")
def __repr__(self):
+10 -10
View File
@@ -70,31 +70,31 @@ class MediaFile(Base, BaseMixin, BaseVideoMixin):
class MediaActor(Base, BaseMixin):
__tablename__ = 'media_actor'
name = Column(String(255))
name = Column(String)
media_actor_files = relationship("MediaActorFile")
class MediaActorFile(Base, BaseMixin):
__tablename__ = 'media_actor_file'
media_actor_id = Column(String(255), ForeignKey("media_actor.id"), nullable=False)
media_actor_id = Column(String, ForeignKey("media_actor.id"), nullable=False)
media_actor = relationship("MediaActor", back_populates="media_actor_files")
media_file_id = Column(String(255), ForeignKey("media_file.id"), nullable=True)
media_file_id = Column(String, ForeignKey("media_file.id"), nullable=True)
media_file = relationship("MediaFile", back_populates="media_actor_files")
class MediaArticle(Base, BaseMixin):
__tablename__ = 'media_article'
review = Column(Boolean)
title = Column(String(255))
url = Column(String(255), unique=True)
title = Column(String)
url = Column(String, unique=True)
class MediaVideo(Base, BaseMixin):
__tablename__ = 'media_video'
cloud_link = Column(String(255))
file_name = Column(String(255))
path = Column(String(255))
cloud_link = Column(String)
file_name = Column(String)
path = Column(String)
review = Column(Boolean)
title = Column(String(255))
url = Column(String(255), unique=True)
title = Column(String)
url = Column(String, unique=True)
should_download = Column(Boolean)
+7 -7
View File
@@ -6,7 +6,7 @@ from src.db.models.base import Base, BaseMixin
class MetaDataTable(Base, BaseMixin):
__tablename__ = 'meta_data_table'
table_name = Column(String(255), unique=True)
table_name = Column(String, unique=True)
table_columns = relationship("MetaDataColumn")
def __repr__(self):
@@ -18,15 +18,15 @@ class MetaDataTable(Base, BaseMixin):
class MetaDataColumn(Base, BaseMixin):
__tablename__ = 'meta_data_column'
column_name = Column(String(255), nullable=False)
column_sync_name = Column(String(255))
column_type = Column(String(255))
column_modifier = Column(String(255), nullable=True)
column_name = Column(String, nullable=False)
column_sync_name = Column(String)
column_type = Column(String)
column_modifier = Column(String, nullable=True)
column_order = Column(Integer)
table_id = Column(String, ForeignKey('meta_data_table.id'))
table = relationship("MetaDataTable", back_populates="table_columns")
column_label = Column(String(255))
filter_label = Column(String(255))
column_label = Column(String)
filter_label = Column(String)
is_shown = Column(Boolean)
show_filter = Column(Boolean)
ref_column = Column(String, nullable=True)
+9 -9
View File
@@ -9,15 +9,15 @@ class Sport(Base, BaseMixin):
__table_args__ = (
UniqueConstraint("name"),
)
name = Column(String(255), nullable=False, index=True, unique=True)
name = Column(String, nullable=False, index=True, unique=True)
teams = relationship("Team")
positions = relationship("FieldPosition")
class Team(Base, BaseMixin):
__tablename__ = "team"
name = Column(String(255), nullable=False, index=True, unique=True)
short_name = Column(String(255), nullable=False, )
name = Column(String, nullable=False, index=True, unique=True)
short_name = Column(String, nullable=False, )
sport_id = Column(String, ForeignKey("sport.id"), nullable=False)
sport = relationship("Sport", back_populates="teams")
roosters = relationship("Rooster")
@@ -29,8 +29,8 @@ class FieldPosition(Base, BaseMixin):
UniqueConstraint("name", "sport_id"),
UniqueConstraint("short_name", "sport_id"),
)
name = Column(String(255), nullable=False, index=True)
short_name = Column(String(255), nullable=False)
name = Column(String, nullable=False, index=True)
short_name = Column(String, nullable=False)
sport_id = Column(String, ForeignKey("sport.id"), nullable=False, index=True)
sport = relationship("Sport", back_populates="positions")
roosters = relationship("Rooster")
@@ -41,8 +41,8 @@ class Player(Base, BaseMixin):
__table_args__ = (
UniqueConstraint("first_name", "last_name"),
)
first_name = Column(String(255), nullable=False, index=True)
last_name = Column(String(255), nullable=False, index=True)
first_name = Column(String, nullable=False, index=True)
last_name = Column(String, nullable=False, index=True)
roosters = relationship("Rooster")
def get_full_name(self) -> str:
@@ -66,7 +66,7 @@ class Rooster(Base, BaseMixin):
class Vendor(Base, BaseMixin):
__tablename__ = "vendor"
name = Column(String(255), nullable=False, unique=True, index=True)
name = Column(String, nullable=False, unique=True, index=True)
card_sets = relationship("CardSet")
cards = relationship("Card")
@@ -76,7 +76,7 @@ class CardSet(Base, BaseMixin):
__table_args__ = (
UniqueConstraint("name", "vendor_id"),
)
name = Column(String(255), index=True)
name = Column(String, index=True)
parallel_set = Column(Boolean)
insert_set = Column(Boolean)
vendor_id = Column(String, ForeignKey("vendor.id"), nullable=False, index=True)
+27
View File
@@ -0,0 +1,27 @@
from typing import List, Type
from sqlalchemy.orm import Session
from src.db.models.comic import Artist, Comic
from src.schema.comics.artist import ArtistDetailResponse
def get_artist_details(artist: Artist) -> ArtistDetailResponse:
works = {}
for work in artist.comic_works:
work_type = work.work_type.name
comic_title = work.comic.title
if work_type in works:
works[work_type].append(comic_title)
else:
works[work_type] = [comic_title]
response = ArtistDetailResponse(
id=artist.id,
name=artist.name,
works=works
)
return response
def list_comics(db: Session) -> List[Type[Comic]]:
comics = db.query(Comic).all()
return comics
+2 -2
View File
@@ -1,7 +1,7 @@
from typing import Generator, Annotated
from typing import Generator
from sqlalchemy import create_engine
from sqlalchemy.orm import sessionmaker, Session
from sqlalchemy.orm import sessionmaker
from src.core.config import settings
+7 -1
View File
@@ -1,3 +1,5 @@
import logging
from fastapi import FastAPI
from fastapi.staticfiles import StaticFiles
@@ -7,6 +9,10 @@ from src.webapps.base import api_router as web_app_router
from src.core.config import settings
from src.db.models.base import Base
logging.basicConfig(level=logging.INFO,
format='%(asctime)s - %(name)s - %(levelname)s - %(message)s',
handlers=[logging.StreamHandler()]) # Logs to console
def include_router(app: FastAPI):
app.include_router(api_router)
app.include_router(web_app_router)
@@ -18,6 +24,7 @@ def create_tables():
Base.metadata.create_all(bind=engine)
def start_application():
logging.info(f"using database: {settings.DATABASE_URL}")
app = FastAPI(title=settings.PROJECT_NAME, version=settings.PROJECT_VERSION)
include_router(app)
configure_static(app)
@@ -26,4 +33,3 @@ def start_application():
kontor = start_application()
+3 -19
View File
@@ -7,30 +7,14 @@ from src.db.models.comic import Artist
class ArtistCreation(BaseModel):
id: str
name: str
class ArtistResponse(BaseModel):
id: UUID
id: str
name: str
class ArtistDetailResponse(BaseModel):
id: UUID
id: str
name: str
works: Dict[str, List[str]]
def get_artist_details(artist: Artist) -> ArtistDetailResponse:
works = {}
for work in artist.comic_works:
work_type = work.work_type.name
comic_title = work.comic.title
if work_type in works:
works[work_type].append(comic_title)
else:
works[work_type] = [comic_title]
response = ArtistDetailResponse(
id=artist.id,
name=artist.name,
works=works
)
return response
+2 -2
View File
@@ -7,12 +7,12 @@ from src.db.models.comic import Comic
class ComicResponse(BaseModel):
id: UUID
id: str
title: str
completed: bool
class ComicDetailsResponse(BaseModel):
id: UUID
id: str
created: str
title: str
completed : bool
+5 -7
View File
@@ -1,10 +1,8 @@
from uuid import UUID
from fastapi import APIRouter, Request
from fastapi.templating import Jinja2Templates
from src.apis.utils import SessionDep
from src.db.models.comic import Comic, Artist, Publisher
from typing import AnyStr
templates = Jinja2Templates(directory="src/templates")
router = APIRouter(include_in_schema=False, prefix="/comic")
@@ -15,7 +13,7 @@ def get_comics(db: SessionDep, request: Request, msg: str = None):
return templates.TemplateResponse("comic/comics.html", {"request": request, "msg": msg, "comics": comics})
@router.get("/comics/{comic_id}")
def comic_details(comic_id: UUID, request: Request, db: SessionDep):
def comic_details(comic_id: AnyStr, request: Request, db: SessionDep):
comic = db.get(Comic, comic_id)
return templates.TemplateResponse("comic/comic_detail.html", {"request": request, "comic":comic})
@@ -25,8 +23,8 @@ def get_artists(db: SessionDep, request: Request, msg: str = None):
return templates.TemplateResponse("comic/artists.html", {"request": request, "msg": msg, "artists": artists})
@router.get("/artists/{artist_id}")
def artist_detail(artist_id: UUID, request: Request, db: SessionDep):
artist = db.get(Artist, artist_id)
def artist_detail(artist_id: AnyStr, request: Request, db: SessionDep):
artist = db.get(Artist, str(artist_id))
return templates.TemplateResponse("comic/artist_detail.html", {"request": request, "artist": artist})
@router.get("/publishers")
@@ -35,7 +33,7 @@ def get_publishers(db: SessionDep, request: Request, msg: str = None):
return templates.TemplateResponse("comic/publishers.html", {"request": request, "publishers": publishers})
@router.get("/publishers/{publisher_id}")
def publisher_details(publisher_id: UUID, request: Request, db: SessionDep, msg: str = None):
def publisher_details(publisher_id: AnyStr, request: Request, db: SessionDep, msg: str = None):
publisher = db.get(Publisher, publisher_id)
if publisher is None:
msg = "Could not find Publisher"