add CRUD for WorkType
This commit is contained in:
@@ -0,0 +1,86 @@
|
||||
from db.models.admin import (
|
||||
Assignment,
|
||||
Token,
|
||||
Profile,
|
||||
Permission,
|
||||
MailAccount,
|
||||
ModuleData,
|
||||
Mail,
|
||||
)
|
||||
from db.models.bookshelf import (
|
||||
ArticleAuthor,
|
||||
BookAuthor,
|
||||
BookshelfPublisher,
|
||||
Article,
|
||||
Book,
|
||||
Author,
|
||||
)
|
||||
from db.models.comic import (
|
||||
Issue,
|
||||
StoryArc,
|
||||
TradePaperback,
|
||||
Volume,
|
||||
ComicWork,
|
||||
Artist,
|
||||
Comic,
|
||||
Publisher,
|
||||
WorkType,
|
||||
)
|
||||
from db.models.media import (
|
||||
MediaFile,
|
||||
MediaActor,
|
||||
MediaActorFile,
|
||||
MediaArticle,
|
||||
MediaVideo,
|
||||
)
|
||||
from db.models.metadata import MetaDataColumn, MetaDataTable
|
||||
from db.models.tysc import (
|
||||
Card,
|
||||
CardSet,
|
||||
Rooster,
|
||||
Team,
|
||||
FieldPosition,
|
||||
Player,
|
||||
Vendor,
|
||||
Sport,
|
||||
)
|
||||
|
||||
registry = {
|
||||
Card.__tablename__: Card,
|
||||
CardSet.__tablename__: CardSet,
|
||||
Rooster.__tablename__: Rooster,
|
||||
Team.__tablename__: Team,
|
||||
FieldPosition.__tablename__: FieldPosition,
|
||||
Player.__tablename__: Player,
|
||||
Vendor.__tablename__: Vendor,
|
||||
Sport.__tablename__: Sport,
|
||||
Issue.__tablename__: Issue,
|
||||
TradePaperback.__tablename__: TradePaperback,
|
||||
StoryArc.__tablename__: StoryArc,
|
||||
Volume.__tablename__: Volume,
|
||||
ComicWork.__tablename__: ComicWork,
|
||||
Artist.__tablename__: Artist,
|
||||
Comic.__tablename__: Comic,
|
||||
Publisher.__tablename__: Publisher,
|
||||
WorkType.__tablename__: WorkType,
|
||||
ArticleAuthor.__tablename__: ArticleAuthor,
|
||||
BookAuthor.__tablename__: BookAuthor,
|
||||
BookshelfPublisher.__tablename__: BookshelfPublisher,
|
||||
Article.__tablename__: Article,
|
||||
Book.__tablename__: Book,
|
||||
Author.__tablename__: Author,
|
||||
MediaFile.__tablename__: MediaFile,
|
||||
MediaActor.__tablename__: MediaActor,
|
||||
MediaActorFile.__tablename__: MediaActorFile,
|
||||
MediaArticle.__tablename__: MediaArticle,
|
||||
MediaVideo.__tablename__: MediaVideo,
|
||||
MetaDataColumn.__tablename__: MetaDataColumn,
|
||||
MetaDataTable.__tablename__: MetaDataTable,
|
||||
Assignment.__tablename__: Assignment,
|
||||
Token.__tablename__: Token,
|
||||
Profile.__tablename__: Profile,
|
||||
Permission.__tablename__: Permission,
|
||||
ModuleData.__tablename__: ModuleData,
|
||||
MailAccount.__tablename__: MailAccount,
|
||||
Mail.__tablename__: Mail
|
||||
}
|
||||
@@ -3,16 +3,16 @@ from datetime import datetime
|
||||
from sqlalchemy import Column, ForeignKey, Integer, String, Boolean
|
||||
from sqlalchemy.orm import relationship, mapped_column, Mapped
|
||||
|
||||
from .base import Base, BaseMixin
|
||||
from 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,11 +30,11 @@ 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")
|
||||
|
||||
|
||||
@@ -1,7 +1,7 @@
|
||||
from sqlalchemy import Column, ForeignKey, Integer, String
|
||||
from sqlalchemy.orm import relationship
|
||||
|
||||
from .base import Base, BaseMixin
|
||||
from db.models.base import Base, BaseMixin
|
||||
|
||||
|
||||
class Article(Base, BaseMixin):
|
||||
@@ -1,12 +1,22 @@
|
||||
from sqlalchemy import Column, ForeignKey, Integer, String, Boolean
|
||||
from sqlalchemy.orm import relationship
|
||||
import uuid
|
||||
from datetime import datetime
|
||||
from typing import List, Optional
|
||||
from sqlalchemy import Column, ForeignKey, Integer, String, Boolean, func
|
||||
from sqlalchemy.orm import relationship, Mapped, mapped_column
|
||||
|
||||
from .base import Base, BaseMixin
|
||||
from db.models.base import Base, BaseMixin
|
||||
|
||||
|
||||
class Publisher(Base, BaseMixin):
|
||||
class Publisher(Base):
|
||||
__tablename__ = "publisher"
|
||||
id: Mapped[str] = mapped_column(primary_key=True, default=uuid.uuid4)
|
||||
created_date: Mapped[datetime] = mapped_column(default=func.now())
|
||||
last_modified_date: Mapped[datetime] = mapped_column(default=func.now())
|
||||
version: Mapped[int] = mapped_column(default=0)
|
||||
name = Column(String, unique=True)
|
||||
parent_publisher_id: Mapped[Optional[str]] = mapped_column(ForeignKey('publisher.id'))
|
||||
parent_publisher: Mapped[Optional['Publisher']] = relationship("Publisher", back_populates="imprints", remote_side=[id])
|
||||
imprints: Mapped[List['Publisher']] = relationship('Publisher', back_populates="parent_publisher")
|
||||
comics = relationship("Comic")
|
||||
|
||||
def __repr__(self):
|
||||
@@ -23,6 +33,7 @@ class Comic(Base, BaseMixin):
|
||||
publisher = relationship("Publisher", back_populates="comics")
|
||||
current_order = Column(Boolean)
|
||||
completed = Column(Boolean)
|
||||
weblink = Column(String, nullable=True)
|
||||
issues = relationship("Issue")
|
||||
story_arcs = relationship("StoryArc")
|
||||
trade_paperbacks = relationship("TradePaperback")
|
||||
@@ -74,6 +85,7 @@ class Issue(Base, BaseMixin):
|
||||
class Artist(Base, BaseMixin):
|
||||
__tablename__ = "artist"
|
||||
name = Column(String, nullable=False)
|
||||
weblink = Column(String, nullable=True)
|
||||
comic_works = relationship("ComicWork")
|
||||
|
||||
|
||||
@@ -97,3 +109,4 @@ class ComicWork(Base, BaseMixin):
|
||||
artist = relationship("Artist", back_populates="comic_works")
|
||||
work_type_id = Column(String, ForeignKey("worktype.id"), nullable=False)
|
||||
work_type = relationship("WorkType", back_populates="comic_works")
|
||||
|
||||
@@ -6,16 +6,17 @@ from logging import Logger
|
||||
from pathlib import Path
|
||||
from typing import Any
|
||||
|
||||
from sqlalchemy import UUID, select
|
||||
from sqlalchemy import select
|
||||
from sqlalchemy.exc import IntegrityError
|
||||
from sqlalchemy.orm import sessionmaker
|
||||
|
||||
from .tysc import Card, CardSet, Rooster, Team, FieldPosition, Player, Vendor, Sport
|
||||
from .comic import Issue, TradePaperback, StoryArc, Volume, ComicWork, Artist, Comic, Publisher, WorkType
|
||||
from .bookshelf import ArticleAuthor, BookAuthor, BookshelfPublisher, Article, Book, Author
|
||||
from .admin import Mail, MailAccount, ModuleData, Permission, Profile, Token, Assignment
|
||||
from .metadata import MetaDataTable, MetaDataColumn
|
||||
from .media import MediaVideo, MediaArticle, MediaFile, MediaActor, MediaActorFile
|
||||
from db.models import registry
|
||||
from db.models.tysc import Card, CardSet, Rooster, Team, FieldPosition, Player, Vendor, Sport
|
||||
from db.models.comic import Issue, TradePaperback, StoryArc, Volume, ComicWork, Artist, Comic, Publisher, WorkType
|
||||
from db.models.bookshelf import ArticleAuthor, BookAuthor, BookshelfPublisher, Article, Book, Author
|
||||
from db.models.admin import Mail, MailAccount, ModuleData, Permission, Profile, Token, Assignment
|
||||
from db.models.metadata import MetaDataTable, MetaDataColumn
|
||||
from db.models.media import MediaVideo, MediaArticle, MediaFile, MediaActor, MediaActorFile
|
||||
|
||||
|
||||
class ColumnEntry(Enum):
|
||||
@@ -46,57 +47,8 @@ class KontorDB:
|
||||
|
||||
def __init__(self, db_engine: Any, log: Logger):
|
||||
self.engine = db_engine
|
||||
self.registry = {}
|
||||
self.init_registry()
|
||||
self.log = log
|
||||
|
||||
def init_registry(self):
|
||||
self.registry[Card.__tablename__] = Card
|
||||
self.registry[CardSet.__tablename__] = CardSet
|
||||
self.registry[Rooster.__tablename__] = Rooster
|
||||
self.registry[Team.__tablename__] = Team
|
||||
self.registry[FieldPosition.__tablename__] = FieldPosition
|
||||
self.registry[Player.__tablename__] = Player
|
||||
self.registry[Vendor.__tablename__] = Vendor
|
||||
self.registry[Sport.__tablename__] = Sport
|
||||
self.registry[Issue.__tablename__] = Issue
|
||||
self.registry[TradePaperback.__tablename__] = TradePaperback
|
||||
self.registry[StoryArc.__tablename__] = StoryArc
|
||||
self.registry[Volume.__tablename__] = Volume
|
||||
self.registry[ComicWork.__tablename__] = ComicWork
|
||||
self.registry[Artist.__tablename__] = Artist
|
||||
self.registry[Comic.__tablename__] = Comic
|
||||
self.registry[Publisher.__tablename__] = Publisher
|
||||
self.registry[WorkType.__tablename__] = WorkType
|
||||
self.registry[ArticleAuthor.__tablename__] = ArticleAuthor
|
||||
self.registry[BookAuthor.__tablename__] = BookAuthor
|
||||
self.registry[BookshelfPublisher.__tablename__] = BookshelfPublisher
|
||||
self.registry[Article.__tablename__] = Article
|
||||
self.registry[Book.__tablename__] = Book
|
||||
self.registry[Author.__tablename__] = Author
|
||||
self.registry[MediaFile.__tablename__] = MediaFile
|
||||
self.registry[MediaActor.__tablename__] = MediaActor
|
||||
self.registry[MediaActorFile.__tablename__] = MediaActorFile
|
||||
self.registry[MediaArticle.__tablename__] = MediaArticle
|
||||
self.registry[MediaVideo.__tablename__] = MediaVideo
|
||||
self.registry[MetaDataColumn.__tablename__] = MetaDataColumn
|
||||
self.registry[MetaDataTable.__tablename__] = MetaDataTable
|
||||
self.registry[Assignment.__tablename__] = Assignment
|
||||
self.registry[Token.__tablename__] = Token
|
||||
self.registry[Profile.__tablename__] = Profile
|
||||
self.registry[Permission.__tablename__] = Permission
|
||||
self.registry[ModuleData.__tablename__] = ModuleData
|
||||
self.registry[MailAccount.__tablename__] = MailAccount
|
||||
self.registry[Mail.__tablename__] = Mail
|
||||
|
||||
def get_table_names(self) -> list:
|
||||
result = []
|
||||
__session__ = sessionmaker(self.engine)
|
||||
with __session__() as session:
|
||||
tables = session.scalars(select(MetaDataTable)).all()
|
||||
result = [table.table_name for table in tables]
|
||||
return result
|
||||
|
||||
def get_table_by_name(self, table_name: str) -> dict:
|
||||
result = {}
|
||||
__session__ = sessionmaker(self.engine)
|
||||
@@ -130,19 +82,6 @@ class KontorDB:
|
||||
order += 1
|
||||
return meta_data
|
||||
|
||||
def get_columns(self, table_name: str) -> dict:
|
||||
columns = {}
|
||||
__session__ = sessionmaker(self.engine)
|
||||
table_info = self.get_table_by_name(table_name)
|
||||
_filters = {'table_id': table_info['id']}
|
||||
with __session__() as session:
|
||||
for column in session.query(MetaDataColumn).filter_by(**_filters).all():
|
||||
columns[column.column_name] = {
|
||||
ColumnEntry.COLUMN_ORDER: column.column_order,
|
||||
ColumnEntry.COLUMN_TYPE: column.column_type
|
||||
}
|
||||
return columns
|
||||
|
||||
def get_filters(self, table_name: str) -> dict:
|
||||
_filter_map = {}
|
||||
__session__ = sessionmaker(self.engine)
|
||||
@@ -159,7 +98,7 @@ class KontorDB:
|
||||
def data(self, table_name: str, columns: dict, filters: dict) -> list:
|
||||
data = []
|
||||
__session__ = sessionmaker(self.engine)
|
||||
table = self.registry[table_name]
|
||||
table = registry[table_name]
|
||||
with __session__() as session:
|
||||
entries = []
|
||||
if len(filters) == 0:
|
||||
@@ -363,7 +302,7 @@ class KontorDB:
|
||||
update_list[link.id] = link.title
|
||||
return update_list
|
||||
|
||||
def get_download_list(self) -> list[UUID]:
|
||||
def get_download_list(self) -> list[str]:
|
||||
download_list = []
|
||||
__session__ = sessionmaker(self.engine)
|
||||
_filter = {'should_download': True}
|
||||
@@ -8,7 +8,7 @@ from bs4 import BeautifulSoup
|
||||
from sqlalchemy import Boolean, Column, False_, String, ForeignKey
|
||||
from sqlalchemy.orm import relationship
|
||||
|
||||
from .base import Base, BaseMixin, BaseVideoMixin
|
||||
from db.models.base import Base, BaseMixin, BaseVideoMixin
|
||||
|
||||
|
||||
class MediaFile(Base, BaseMixin, BaseVideoMixin):
|
||||
@@ -1,7 +1,7 @@
|
||||
from sqlalchemy import Column, String, ForeignKey, Integer, Boolean
|
||||
from sqlalchemy.orm import relationship
|
||||
|
||||
from .base import Base, BaseMixin
|
||||
from db.models.base import Base, BaseMixin
|
||||
|
||||
|
||||
class MetaDataTable(Base, BaseMixin):
|
||||
@@ -1,7 +1,7 @@
|
||||
from sqlalchemy import Column, Integer, String, ForeignKey, UniqueConstraint, Boolean
|
||||
from sqlalchemy.orm import relationship
|
||||
|
||||
from .base import Base, BaseMixin
|
||||
from db.models.base import Base, BaseMixin
|
||||
|
||||
|
||||
class Sport(Base, BaseMixin):
|
||||
@@ -0,0 +1,28 @@
|
||||
|
||||
from typing import List
|
||||
from sqlalchemy.orm import Session
|
||||
|
||||
from db.models.metadata import MetaDataColumn, MetaDataTable
|
||||
from db.schemas.metadata import MetaDataTableResponse, MetaDataColumnResponse
|
||||
|
||||
|
||||
def get_tables(db: Session) -> List[MetaDataTableResponse]:
|
||||
tables = db.query(MetaDataTable).all()
|
||||
results: List[MetaDataTableResponse] = [MetaDataTableResponse(id=table.id, name=table.table_name) for table in tables]
|
||||
return results
|
||||
|
||||
|
||||
def get_columns_for_table(db: Session, table: MetaDataTableResponse)-> List[MetaDataColumnResponse]:
|
||||
columns = db.query(MetaDataColumn).filter_by(table_id = table.id).all()
|
||||
results: List[MetaDataColumnResponse] = []
|
||||
for column in columns:
|
||||
result: MetaDataColumnResponse = MetaDataColumnResponse(
|
||||
id=str(column.id),
|
||||
name=column.column_name,
|
||||
label=column.column_label,
|
||||
order=column.column_order,
|
||||
ref_column=column.ref_column,
|
||||
column_type=column.column_type)
|
||||
results.append(result)
|
||||
return results
|
||||
|
||||
@@ -0,0 +1,15 @@
|
||||
from pydantic import BaseModel, PositiveInt
|
||||
|
||||
|
||||
class MetaDataTableResponse(BaseModel):
|
||||
id: str
|
||||
name: str
|
||||
|
||||
|
||||
class MetaDataColumnResponse(BaseModel):
|
||||
id: str
|
||||
name: str
|
||||
label: str
|
||||
order: PositiveInt
|
||||
ref_column: str | None
|
||||
column_type: str
|
||||
@@ -80,7 +80,7 @@ def is_file_downloaded(media_file: dict, dir: Path) -> FileStatus:
|
||||
|
||||
|
||||
def update_status(item_id: UUID, file_info: dict):
|
||||
update = requests.put(f"http://127.0.0.1:8800/media/files/{item_id}", json=file_info)
|
||||
update = requests.put(f"http://127.0.0.1:8800/api/media/files/{item_id}", json=file_info)
|
||||
log.info(f"update status: {update.status_code}")
|
||||
log.info(f"update result: {update.json()}")
|
||||
|
||||
@@ -97,7 +97,7 @@ def rename_file(file_info: dict):
|
||||
if __name__ == '__main__':
|
||||
log = get_logger(args.verbose, args.config)
|
||||
log.info('kontor.download started')
|
||||
response = requests.get("http://127.0.0.1:8800/media/files?download=true")
|
||||
response = requests.get("http://127.0.0.1:8800/api/media/files?download=true")
|
||||
log.info(f"Status: {response.status_code}")
|
||||
data = response.json()
|
||||
log.info(f"data: {len(data)}")
|
||||
|
||||
@@ -2,17 +2,17 @@
|
||||
import data from json file to MariaDB
|
||||
"""
|
||||
from argparse import ArgumentParser, ArgumentDefaultsHelpFormatter
|
||||
|
||||
from datetime import datetime
|
||||
import json
|
||||
import yaml
|
||||
from sqlalchemy import create_engine
|
||||
from sqlalchemy.orm import sessionmaker
|
||||
from platformdirs import PlatformDirs
|
||||
from pathlib import Path
|
||||
|
||||
from schema.base import Base
|
||||
from schema.database import KontorDB
|
||||
from db.models import registry
|
||||
from db.models.base import Base
|
||||
from config import get_logger
|
||||
from schema.database import ExportType
|
||||
from db.repository.metadata import get_tables, get_columns_for_table
|
||||
|
||||
parser = ArgumentParser(formatter_class=ArgumentDefaultsHelpFormatter)
|
||||
parser.add_argument('--verbose', '-v', action='count', default=0)
|
||||
@@ -38,6 +38,34 @@ if __name__ == '__main__':
|
||||
engine = create_engine(connect_string)
|
||||
Base.metadata.create_all(bind=engine, checkfirst=True)
|
||||
__session__ = sessionmaker(bind=engine)
|
||||
kontor_db = KontorDB(engine, logger)
|
||||
kontor_db.export_db(ExportType.JSON, args.file)
|
||||
with __session__() as db:
|
||||
data = {}
|
||||
tables = get_tables(db)
|
||||
for table in tables:
|
||||
# logger.info(f"Table {table.name} with {table.id}")
|
||||
columns = get_columns_for_table(db, table)
|
||||
model = registry[table.name]
|
||||
rows = db.query(model).all()
|
||||
entries = []
|
||||
for row in rows:
|
||||
entry = {}
|
||||
for column in columns:
|
||||
# logger.info(f" Column {column.order} {column.name} with {column.id}")
|
||||
try:
|
||||
value = getattr(row, column.name)
|
||||
if isinstance(value, datetime):
|
||||
entry[column.name] = str(value)
|
||||
else:
|
||||
entry[column.name] = value
|
||||
except AttributeError as error:
|
||||
logger.info(f"{error}")
|
||||
entries.append(entry)
|
||||
data[table.name] = entries
|
||||
logger.info(f"{table.name}: {len(entries)} exported")
|
||||
json_dump = json.dumps(data, indent=4)
|
||||
with open(args.file, "w") as dump_file:
|
||||
dump_file.write(json_dump)
|
||||
logger.info(f"{len(data)} tables exported")
|
||||
#kontor_db = KontorDB(engine, logger)
|
||||
#kontor_db.export_db(ExportType.JSON, args.file)
|
||||
logger.info('kontor.export finished')
|
||||
|
||||
@@ -7,7 +7,6 @@ from typing import Dict, List
|
||||
|
||||
from config import get_logger, get_database_cursors
|
||||
import json
|
||||
import psycopg2
|
||||
from psycopg2.sql import SQL
|
||||
|
||||
parser = ArgumentParser(formatter_class=ArgumentDefaultsHelpFormatter)
|
||||
|
||||
@@ -37,7 +37,7 @@ def get_logger(level: int, config: str):
|
||||
if __name__ == '__main__':
|
||||
log = get_logger(args.verbose, args.config)
|
||||
log.info('kontor.update_titles started')
|
||||
response = requests.get("http://127.0.0.1:8800/media/files?review=true")
|
||||
response = requests.get("http://127.0.0.1:8800/api/media/files?review=true")
|
||||
log.info(f"Status: {response.status_code}")
|
||||
data = response.json()
|
||||
log.info(f"data: {len(data)}")
|
||||
@@ -49,11 +49,11 @@ if __name__ == '__main__':
|
||||
soup = BeautifulSoup(r.content, "html.parser")
|
||||
title = soup.title.string
|
||||
item['title'] = title
|
||||
item['review'] = 0
|
||||
item['review'] = False
|
||||
except:
|
||||
item['title'] = None
|
||||
item['review'] = 1
|
||||
update = requests.put(f"http://127.0.0.1:8800/media/files/{item['id']}", json=item)
|
||||
item['review'] = True
|
||||
update = requests.put(f"http://127.0.0.1:8800/api/media/files/{item['id']}", json=item)
|
||||
log.info(f"update status: {update.status_code}")
|
||||
log.info(f"update result: {update.json()}")
|
||||
log.info('kontor.update_titles finished')
|
||||
|
||||
Reference in New Issue
Block a user