- 偿试修复可执行文件打包插件数据表缺失问题

This commit is contained in:
jxxghp 2023-12-05 20:57:53 +08:00
parent 1323cd5dc6
commit f0fbad889d
15 changed files with 79 additions and 99 deletions

View File

@ -1,7 +1,10 @@
from typing import Any, Self, List
from typing import Tuple, Optional, Generator from typing import Tuple, Optional, Generator
from sqlalchemy import create_engine, QueuePool from sqlalchemy import create_engine, QueuePool
from sqlalchemy.orm import sessionmaker, Session, scoped_session from sqlalchemy import inspect
from sqlalchemy.orm import declared_attr
from sqlalchemy.orm import sessionmaker, Session, scoped_session, as_declarative
from app.core.config import settings from app.core.config import settings
@ -135,6 +138,52 @@ def db_query(func):
return wrapper return wrapper
@as_declarative()
class Base:
id: Any
__name__: str
@db_update
def create(self, db: Session):
db.add(self)
@classmethod
@db_query
def get(cls, db: Session, rid: int) -> Self:
return db.query(cls).filter(cls.id == rid).first()
@db_update
def update(self, db: Session, payload: dict):
payload = {k: v for k, v in payload.items() if v is not None}
for key, value in payload.items():
setattr(self, key, value)
if inspect(self).detached:
db.add(self)
@classmethod
@db_update
def delete(cls, db: Session, rid):
db.query(cls).filter(cls.id == rid).delete()
@classmethod
@db_update
def truncate(cls, db: Session):
db.query(cls).delete()
@classmethod
@db_query
def list(cls, db: Session) -> List[Self]:
result = db.query(cls).all()
return list(result)
def to_dict(self):
return {c.name: getattr(self, c.name, None) for c in self.__table__.columns}
@declared_attr
def __tablename__(self) -> str:
return self.__name__.lower()
class DbOper: class DbOper:
""" """
数据库操作基类 数据库操作基类

View File

@ -1,15 +1,10 @@
import importlib
from pathlib import Path
from alembic.command import upgrade from alembic.command import upgrade
from alembic.config import Config from alembic.config import Config
from app.core.config import settings from app.core.config import settings
from app.core.security import get_password_hash from app.core.security import get_password_hash
from app.db import Engine, SessionFactory from app.db import Engine, SessionFactory, Base
from app.db.models import Base from app.db.models import *
from app.db.models.user import User
from app.helper.module import ModuleHelper
from app.log import logger from app.log import logger
@ -17,21 +12,18 @@ def init_db():
""" """
初始化数据库 初始化数据库
""" """
# 导入模块,避免建表缺失
models_path = Path(__file__).with_name("models")
ModuleHelper.dynamic_import_all_modules(models_path, "app.db.models")
# 全量建表 # 全量建表
Base.metadata.create_all(bind=Engine) Base.metadata.create_all(bind=Engine)
# 初始化超级管理员 # 初始化超级管理员
with SessionFactory() as db: with SessionFactory() as db:
user = User.get_by_name(db=db, name=settings.SUPERUSER) _user = User.get_by_name(db=db, name=settings.SUPERUSER)
if not user: if not _user:
user = User( _user = User(
name=settings.SUPERUSER, name=settings.SUPERUSER,
hashed_password=get_password_hash(settings.SUPERUSER_PASSWORD), hashed_password=get_password_hash(settings.SUPERUSER_PASSWORD),
is_superuser=True, is_superuser=True,
) )
user.create(db) _user.create(db)
def update_db(): def update_db():

View File

@ -1,52 +1,9 @@
from typing import Any, Self, List from .downloadhistory import DownloadHistory, DownloadFiles
from .mediaserver import MediaServerItem
from sqlalchemy import inspect from .plugindata import PluginData
from sqlalchemy.orm import as_declarative, declared_attr, Session from .site import Site
from .siteicon import SiteIcon
from app.db import db_update, db_query from .subscribe import Subscribe
from .systemconfig import SystemConfig
from .transferhistory import TransferHistory
@as_declarative() from .user import User
class Base:
id: Any
__name__: str
@db_update
def create(self, db: Session):
db.add(self)
@classmethod
@db_query
def get(cls, db: Session, rid: int) -> Self:
return db.query(cls).filter(cls.id == rid).first()
@db_update
def update(self, db: Session, payload: dict):
payload = {k: v for k, v in payload.items() if v is not None}
for key, value in payload.items():
setattr(self, key, value)
if inspect(self).detached:
db.add(self)
@classmethod
@db_update
def delete(cls, db: Session, rid):
db.query(cls).filter(cls.id == rid).delete()
@classmethod
@db_update
def truncate(cls, db: Session):
db.query(cls).delete()
@classmethod
@db_query
def list(cls, db: Session) -> List[Self]:
result = db.query(cls).all()
return list(result)
def to_dict(self):
return {c.name: getattr(self, c.name, None) for c in self.__table__.columns}
@declared_attr
def __tablename__(self) -> str:
return self.__name__.lower()

View File

@ -1,8 +1,7 @@
from sqlalchemy import Column, Integer, String, Sequence from sqlalchemy import Column, Integer, String, Sequence
from sqlalchemy.orm import Session from sqlalchemy.orm import Session
from app.db import db_query from app.db import db_query, db_update, Base
from app.db.models import Base, db_update
class DownloadHistory(Base): class DownloadHistory(Base):

View File

@ -4,8 +4,7 @@ from typing import Optional
from sqlalchemy import Column, Integer, String, Sequence from sqlalchemy import Column, Integer, String, Sequence
from sqlalchemy.orm import Session from sqlalchemy.orm import Session
from app.db import db_query from app.db import db_query, db_update, Base
from app.db.models import Base, db_update
class MediaServerItem(Base): class MediaServerItem(Base):

View File

@ -1,8 +1,7 @@
from sqlalchemy import Column, Integer, String, Sequence from sqlalchemy import Column, Integer, String, Sequence
from sqlalchemy.orm import Session from sqlalchemy.orm import Session
from app.db import db_query from app.db import db_query, db_update, Base
from app.db.models import Base, db_update
class PluginData(Base): class PluginData(Base):

View File

@ -3,8 +3,7 @@ from datetime import datetime
from sqlalchemy import Boolean, Column, Integer, String, Sequence from sqlalchemy import Boolean, Column, Integer, String, Sequence
from sqlalchemy.orm import Session from sqlalchemy.orm import Session
from app.db import db_query from app.db import db_query, db_update, Base
from app.db.models import Base, db_update
class Site(Base): class Site(Base):

View File

@ -1,8 +1,7 @@
from sqlalchemy import Column, Integer, String, Sequence from sqlalchemy import Column, Integer, String, Sequence
from sqlalchemy.orm import Session from sqlalchemy.orm import Session
from app.db import db_query from app.db import db_query, Base
from app.db.models import Base
class SiteIcon(Base): class SiteIcon(Base):

View File

@ -1,8 +1,7 @@
from sqlalchemy import Column, Integer, String, Sequence from sqlalchemy import Column, Integer, String, Sequence
from sqlalchemy.orm import Session from sqlalchemy.orm import Session
from app.db import db_update, db_query from app.db import db_query, db_update, Base
from app.db.models import Base
class Subscribe(Base): class Subscribe(Base):

View File

@ -1,8 +1,7 @@
from sqlalchemy import Column, Integer, String, Sequence from sqlalchemy import Column, Integer, String, Sequence
from sqlalchemy.orm import Session from sqlalchemy.orm import Session
from app.db import db_update, db_query from app.db import db_query, db_update, Base
from app.db.models import Base
class SystemConfig(Base): class SystemConfig(Base):

View File

@ -3,8 +3,7 @@ import time
from sqlalchemy import Column, Integer, String, Sequence, Boolean, func from sqlalchemy import Column, Integer, String, Sequence, Boolean, func
from sqlalchemy.orm import Session from sqlalchemy.orm import Session
from app.db import db_query from app.db import db_query, db_update, Base
from app.db.models import Base, db_update
class TransferHistory(Base): class TransferHistory(Base):

View File

@ -2,8 +2,7 @@ from sqlalchemy import Boolean, Column, Integer, String, Sequence
from sqlalchemy.orm import Session from sqlalchemy.orm import Session
from app.core.security import verify_password from app.core.security import verify_password
from app.db import db_update, db_query from app.db import db_query, db_update, Base
from app.db.models import Base
class User(Base): class User(Base):

View File

@ -40,7 +40,7 @@ class ModuleHelper:
@staticmethod @staticmethod
def dynamic_import_all_modules(base_path: Path, package_name: str): def dynamic_import_all_modules(base_path: Path, package_name: str):
""" """
动态导入所有模块到全局对象 动态导入目录下所有模块
""" """
modules = [] modules = []
# 遍历文件夹,找到所有模块文件 # 遍历文件夹,找到所有模块文件
@ -48,14 +48,5 @@ class ModuleHelper:
file_name = file.stem file_name = file.stem
if file_name != "__init__": if file_name != "__init__":
modules.append(file_name) modules.append(file_name)
# 保存已有的全局对象 full_module_name = f"{package_name}.{file_name}"
existing_globals = set(globals().keys()) importlib.import_module(full_module_name)
# 动态导入并添加到全局命名空间
for module in modules:
full_module_name = f"{package_name}.{module}"
import_module = importlib.import_module(full_module_name)
module_globals = import_module.__dict__
# 仅导入全局对象中不存在的部分
new_objects = {name: value for name, value in module_globals.items() if name not in existing_globals}
# 更新全局命名空间
globals().update(new_objects)

View File

@ -5,7 +5,7 @@ from sqlalchemy import pool
from alembic import context from alembic import context
from app.db.models import Base from app.db import Base
# this is the Alembic Config object, which provides # this is the Alembic Config object, which provides
# access to the values within the .ini file in use. # access to the values within the .ini file in use.
config = context.config config = context.config

View File

@ -1 +1 @@
APP_VERSION = 'v1.4.8-1' APP_VERSION = 'v1.4.8-2'