From 4148e362b9d65957bec67c0f047f2d13a16a7ce0 Mon Sep 17 00:00:00 2001 From: Yuerchu Date: Fri, 18 Jul 2025 00:50:19 +0800 Subject: [PATCH] =?UTF-8?q?=E6=95=B0=E6=8D=AE=E5=BA=93=E6=97=B6=E9=97=B4?= =?UTF-8?q?=E6=97=A5=E5=BF=97=E8=BF=81=E7=A7=BB=E8=87=B3=20BaseModel?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- models/base.py | 24 ++++++++++++++++++++++-- models/download.py | 29 ----------------------------- models/file.py | 29 ----------------------------- models/folder.py | 20 -------------------- models/group.py | 20 -------------------- models/node.py | 29 ----------------------------- models/order.py | 29 ----------------------------- models/policy.py | 29 ----------------------------- models/redeem.py | 22 +--------------------- models/report.py | 29 ----------------------------- models/setting.py | 29 ----------------------------- models/share.py | 29 ----------------------------- models/source_link.py | 29 ----------------------------- models/storage_pack.py | 28 ---------------------------- models/tag.py | 29 ----------------------------- models/task.py | 29 ----------------------------- models/user.py | 29 ----------------------------- models/webdav.py | 32 +------------------------------- tests/test_database.py | 4 ++-- tests/test_db_group.py | 4 +++- tests/test_db_user.py | 4 +++- 21 files changed, 32 insertions(+), 474 deletions(-) diff --git a/models/base.py b/models/base.py index 2d4eb92..9e318a8 100644 --- a/models/base.py +++ b/models/base.py @@ -1,7 +1,27 @@ from typing import Optional from sqlmodel import SQLModel, Field +from sqlalchemy import DateTime +from datetime import datetime, timezone +from sqlalchemy.ext.asyncio import AsyncAttrs -class BaseModel(SQLModel): +utcnow = lambda: datetime.now(tz=timezone.utc) + +class BaseModel(SQLModel, AsyncAttrs): __abstract__ = True - id: Optional[int] = Field(default=None, primary_key=True, description="主键ID") \ No newline at end of file + id: Optional[int] = Field(default=None, primary_key=True, description="主键ID") + created_at: datetime = Field( + default_factory=utcnow, + description="创建时间", + ) + updated_at: datetime = Field( + sa_type=DateTime, + description="更新时间", + sa_column_kwargs={"default": utcnow, "onupdate": utcnow}, + default_factory=utcnow + ) + deleted_at: Optional[datetime] = Field( + default=None, + description="删除时间", + sa_column={"nullable": True} + ) \ No newline at end of file diff --git a/models/download.py b/models/download.py index 74f24c3..8e1077b 100644 --- a/models/download.py +++ b/models/download.py @@ -24,35 +24,6 @@ class Download(BaseModel, table=True): attrs: Optional[str] = Field(default=None, description="额外属性 (JSON格式)") error: Optional[str] = Field(default=None, description="错误信息") dst: str = Field(description="目标存储路径") - created_at: Optional[datetime] = Field( - default=None, - sa_column=Column( - DateTime, - nullable=False, - server_default=func.now(), - comment="创建时间", - ), - ) - - updated_at: Optional[datetime] = Field( - default=None, - sa_column=Column( - DateTime, - nullable=False, - server_default=func.now(), - onupdate=func.now(), - comment="更新时间", - ), - ) - - delete_at: Optional[datetime] = Field( - default=None, - sa_column=Column( - DateTime, - nullable=True, - comment="删除时间", - ), - ) # 外键 user_id: int = Field(foreign_key="users.id", index=True, description="所属用户ID") diff --git a/models/file.py b/models/file.py index 59a155e..33f1d9f 100644 --- a/models/file.py +++ b/models/file.py @@ -20,35 +20,6 @@ class File(BaseModel, table=True): pic_info: Optional[str] = Field(default=None, max_length=255, description="图片信息(如尺寸)") upload_session_id: Optional[str] = Field(default=None, max_length=255, unique=True, index=True, description="分块上传会话ID") file_metadata: Optional[str] = Field(default=None, description="文件元数据 (JSON格式)") - created_at: Optional[datetime] = Field( - default=None, - sa_column=Column( - DateTime, - nullable=False, - server_default=func.now(), - comment="创建时间", - ), - ) - - updated_at: Optional[datetime] = Field( - default=None, - sa_column=Column( - DateTime, - nullable=False, - server_default=func.now(), - onupdate=func.now(), - comment="更新时间", - ), - ) - - delete_at: Optional[datetime] = Field( - default=None, - sa_column=Column( - DateTime, - nullable=True, - comment="删除时间", - ), - ) # 外键 user_id: int = Field(foreign_key="users.id", index=True, description="所属用户ID") diff --git a/models/folder.py b/models/folder.py index bf7e208..9eaa541 100644 --- a/models/folder.py +++ b/models/folder.py @@ -15,26 +15,6 @@ class Folder(BaseModel, table=True): __table_args__ = (UniqueConstraint("name", "parent_id", name="uq_folder_name_parent"),) name: str = Field(max_length=255, description="目录名") - created_at: Optional[datetime] = Field( - default=None, - sa_column=Column( - DateTime, - nullable=False, - server_default=func.now(), - comment="创建时间", - ), - ) - - updated_at: Optional[datetime] = Field( - default=None, - sa_column=Column( - DateTime, - nullable=False, - server_default=func.now(), - onupdate=func.now(), - comment="更新时间", - ), - ) # 外键 parent_id: Optional[int] = Field(default=None, foreign_key="folders.id", index=True, description="父目录ID") diff --git a/models/group.py b/models/group.py index 16f2974..9f2609e 100644 --- a/models/group.py +++ b/models/group.py @@ -19,26 +19,6 @@ class Group(BaseModel, table=True): web_dav_enabled: bool = Field(default=False, sa_column_kwargs={"server_default": text("false")}, description="是否允许使用WebDAV") speed_limit: int = Field(default=0, sa_column_kwargs={"server_default": "0"}, description="速度限制 (KB/s), 0为不限制") options: Optional[str] = Field(default=None, description="其他选项 (JSON格式)") - created_at: Optional[datetime] = Field( - default=None, - sa_column=Column( - DateTime, - nullable=False, - server_default=func.now(), - comment="创建时间", - ), - ) - - updated_at: Optional[datetime] = Field( - default=None, - sa_column=Column( - DateTime, - nullable=False, - server_default=func.now(), - onupdate=func.now(), - comment="更新时间", - ), - ) # 关系:一个组可以有多个用户 users: List["User"] = Relationship( diff --git a/models/node.py b/models/node.py index a7ccb1f..8a39e9a 100644 --- a/models/node.py +++ b/models/node.py @@ -20,35 +20,6 @@ class Node(BaseModel, table=True): aria2_enabled: bool = Field(default=False, sa_column_kwargs={"server_default": text("false")}, description="是否启用Aria2") aria2_options: Optional[str] = Field(default=None, description="Aria2配置 (JSON格式)") rank: int = Field(default=0, sa_column_kwargs={"server_default": "0"}, description="节点排序权重") - created_at: Optional[datetime] = Field( - default=None, - sa_column=Column( - DateTime, - nullable=False, - server_default=func.now(), - comment="创建时间", - ), - ) - - updated_at: Optional[datetime] = Field( - default=None, - sa_column=Column( - DateTime, - nullable=False, - server_default=func.now(), - onupdate=func.now(), - comment="更新时间", - ), - ) - - delete_at: Optional[datetime] = Field( - default=None, - sa_column=Column( - DateTime, - nullable=True, - comment="删除时间", - ), - ) # 关系 downloads: list["Download"] = Relationship(back_populates="node") \ No newline at end of file diff --git a/models/order.py b/models/order.py index 6a9da95..2ebb0c5 100644 --- a/models/order.py +++ b/models/order.py @@ -19,35 +19,6 @@ class Order(BaseModel, table=True): name: str = Field(max_length=255, description="商品名称") price: int = Field(default=0, sa_column_kwargs={"server_default": "0"}, description="订单价格(分)") status: int = Field(default=0, sa_column_kwargs={"server_default": "0"}, description="订单状态: 0=待支付, 1=已完成, 2=已取消") - created_at: Optional[datetime] = Field( - default=None, - sa_column=Column( - DateTime, - nullable=False, - server_default=func.now(), - comment="创建时间", - ), - ) - - updated_at: Optional[datetime] = Field( - default=None, - sa_column=Column( - DateTime, - nullable=False, - server_default=func.now(), - onupdate=func.now(), - comment="更新时间", - ), - ) - - delete_at: Optional[datetime] = Field( - default=None, - sa_column=Column( - DateTime, - nullable=True, - comment="删除时间", - ), - ) # 外键 user_id: int = Field(foreign_key="users.id", index=True, description="所属用户ID") diff --git a/models/policy.py b/models/policy.py index 9e62dff..b1c2d17 100644 --- a/models/policy.py +++ b/models/policy.py @@ -26,35 +26,6 @@ class Policy(BaseModel, table=True): file_name_rule: Optional[str] = Field(default=None, max_length=255, description="文件命名规则") is_origin_link_enable: bool = Field(default=False, sa_column_kwargs={"server_default": text("false")}, description="是否开启源链接访问") options: Optional[str] = Field(default=None, description="其他选项 (JSON格式)") - created_at: Optional[datetime] = Field( - default=None, - sa_column=Column( - DateTime, - nullable=False, - server_default=func.now(), - comment="创建时间", - ), - ) - - updated_at: Optional[datetime] = Field( - default=None, - sa_column=Column( - DateTime, - nullable=False, - server_default=func.now(), - onupdate=func.now(), - comment="更新时间", - ), - ) - - delete_at: Optional[datetime] = Field( - default=None, - sa_column=Column( - DateTime, - nullable=True, - comment="删除时间", - ), - ) # 关系 files: List["File"] = Relationship(back_populates="policy") diff --git a/models/redeem.py b/models/redeem.py index eb40758..4b6e594 100644 --- a/models/redeem.py +++ b/models/redeem.py @@ -12,24 +12,4 @@ class Redeem(BaseModel, table=True): product_id: Optional[int] = Field(default=None, description="关联的商品/权益ID") num: int = Field(default=1, sa_column_kwargs={"server_default": "1"}, description="可兑换数量/时长等") code: str = Field(unique=True, index=True, description="兑换码,唯一") - used: bool = Field(default=False, sa_column_kwargs={"server_default": text("false")}, description="是否已使用") - created_at: Optional[datetime] = Field( - default=None, - sa_column=Column( - DateTime, - nullable=False, - server_default=func.now(), - comment="创建时间", - ), - ) - - updated_at: Optional[datetime] = Field( - default=None, - sa_column=Column( - DateTime, - nullable=False, - server_default=func.now(), - onupdate=func.now(), - comment="更新时间", - ), - ) \ No newline at end of file + used: bool = Field(default=False, sa_column_kwargs={"server_default": text("false")}, description="是否已使用") \ No newline at end of file diff --git a/models/report.py b/models/report.py index 87c3a4f..764a038 100644 --- a/models/report.py +++ b/models/report.py @@ -13,35 +13,6 @@ class Report(BaseModel, table=True): reason: int = Field(description="举报原因代码") description: Optional[str] = Field(default=None, max_length=255, description="补充描述") - created_at: Optional[datetime] = Field( - default=None, - sa_column=Column( - DateTime, - nullable=False, - server_default=func.now(), - comment="创建时间", - ), - ) - - updated_at: Optional[datetime] = Field( - default=None, - sa_column=Column( - DateTime, - nullable=False, - server_default=func.now(), - onupdate=func.now(), - comment="更新时间", - ), - ) - - delete_at: Optional[datetime] = Field( - default=None, - sa_column=Column( - DateTime, - nullable=True, - comment="删除时间", - ), - ) # 外键 share_id: int = Field(foreign_key="shares.id", index=True, description="被举报的分享ID") diff --git a/models/setting.py b/models/setting.py index 1a399a4..f6cb13c 100644 --- a/models/setting.py +++ b/models/setting.py @@ -41,35 +41,6 @@ class Setting(BaseModel, table=True): type: str = Field(max_length=255, description="设置类型/分组") name: str = Field(max_length=255, description="设置项名称") value: Optional[str] = Field(default=None, description="设置值") - created_at: Optional[datetime] = Field( - default=None, - sa_column=Column( - DateTime, - nullable=False, - server_default=func.now(), - comment="创建时间", - ), - ) - - updated_at: Optional[datetime] = Field( - default=None, - sa_column=Column( - DateTime, - nullable=False, - server_default=func.now(), - onupdate=func.now(), - comment="更新时间", - ), - ) - - delete_at: Optional[datetime] = Field( - default=None, - sa_column=Column( - DateTime, - nullable=True, - comment="删除时间", - ), - ) @staticmethod async def add( diff --git a/models/share.py b/models/share.py index c37611d..2f4e2bf 100644 --- a/models/share.py +++ b/models/share.py @@ -23,35 +23,6 @@ class Share(BaseModel, table=True): preview_enabled: bool = Field(default=True, sa_column_kwargs={"server_default": text("true")}, description="是否允许预览") source_name: Optional[str] = Field(default=None, max_length=255, index=True, description="源名称(冗余字段,便于展示)") score: int = Field(default=0, sa_column_kwargs={"server_default": "0"}, description="兑换此分享所需的积分") - created_at: Optional[datetime] = Field( - default=None, - sa_column=Column( - DateTime, - nullable=False, - server_default=func.now(), - comment="创建时间", - ), - ) - - updated_at: Optional[datetime] = Field( - default=None, - sa_column=Column( - DateTime, - nullable=False, - server_default=func.now(), - onupdate=func.now(), - comment="更新时间", - ), - ) - - delete_at: Optional[datetime] = Field( - default=None, - sa_column=Column( - DateTime, - nullable=True, - comment="删除时间", - ), - ) # 外键 user_id: int = Field(foreign_key="users.id", index=True, description="创建分享的用户ID") diff --git a/models/source_link.py b/models/source_link.py index 8142ab1..9c5d3fb 100644 --- a/models/source_link.py +++ b/models/source_link.py @@ -13,35 +13,6 @@ class SourceLink(BaseModel, table=True): name: str = Field(max_length=255, description="链接名称") downloads: int = Field(default=0, sa_column_kwargs={"server_default": "0"}, description="通过此链接的下载次数") - created_at: Optional[datetime] = Field( - default=None, - sa_column=Column( - DateTime, - nullable=False, - server_default=func.now(), - comment="创建时间", - ), - ) - - updated_at: Optional[datetime] = Field( - default=None, - sa_column=Column( - DateTime, - nullable=False, - server_default=func.now(), - onupdate=func.now(), - comment="更新时间", - ), - ) - - delete_at: Optional[datetime] = Field( - default=None, - sa_column=Column( - DateTime, - nullable=True, - comment="删除时间", - ), - ) # 外键 file_id: int = Field(foreign_key="files.id", index=True, description="关联的文件ID") diff --git a/models/storage_pack.py b/models/storage_pack.py index a843593..2052ef2 100644 --- a/models/storage_pack.py +++ b/models/storage_pack.py @@ -16,35 +16,7 @@ class StoragePack(BaseModel, table=True): active_time: Optional[datetime] = Field(default=None, description="激活时间") expired_time: Optional[datetime] = Field(default=None, index=True, description="过期时间") size: int = Field(description="容量包大小(字节)") - created_at: Optional[datetime] = Field( - default=None, - sa_column=Column( - DateTime, - nullable=False, - server_default=func.now(), - comment="创建时间", - ), - ) - - updated_at: Optional[datetime] = Field( - default=None, - sa_column=Column( - DateTime, - nullable=False, - server_default=func.now(), - onupdate=func.now(), - comment="更新时间", - ), - ) - delete_at: Optional[datetime] = Field( - default=None, - sa_column=Column( - DateTime, - nullable=True, - comment="删除时间", - ), - ) # 外键 user_id: int = Field(foreign_key="users.id", index=True, description="所属用户ID") diff --git a/models/tag.py b/models/tag.py index 3d7f8fc..9831813 100644 --- a/models/tag.py +++ b/models/tag.py @@ -17,35 +17,6 @@ class Tag(BaseModel, table=True): color: Optional[str] = Field(default=None, max_length=255, description="标签颜色") type: int = Field(default=0, sa_column_kwargs={"server_default": "0"}, description="标签类型: 0=手动, 1=自动") expression: Optional[str] = Field(default=None, description="自动标签的匹配表达式") - created_at: Optional[datetime] = Field( - default=None, - sa_column=Column( - DateTime, - nullable=False, - server_default=func.now(), - comment="创建时间", - ), - ) - - updated_at: Optional[datetime] = Field( - default=None, - sa_column=Column( - DateTime, - nullable=False, - server_default=func.now(), - onupdate=func.now(), - comment="更新时间", - ), - ) - - delete_at: Optional[datetime] = Field( - default=None, - sa_column=Column( - DateTime, - nullable=True, - comment="删除时间", - ), - ) # 外键 user_id: int = Field(foreign_key="users.id", index=True, description="所属用户ID") diff --git a/models/task.py b/models/task.py index eea0df3..8952df2 100644 --- a/models/task.py +++ b/models/task.py @@ -17,35 +17,6 @@ class Task(BaseModel, table=True): progress: int = Field(default=0, sa_column_kwargs={"server_default": "0"}, description="任务进度 (0-100)") error: Optional[str] = Field(default=None, description="错误信息") props: Optional[str] = Field(default=None, description="任务属性 (JSON格式)") - created_at: Optional[datetime] = Field( - default=None, - sa_column=Column( - DateTime, - nullable=False, - server_default=func.now(), - comment="创建时间", - ), - ) - - updated_at: Optional[datetime] = Field( - default=None, - sa_column=Column( - DateTime, - nullable=False, - server_default=func.now(), - onupdate=func.now(), - comment="更新时间", - ), - ) - - delete_at: Optional[datetime] = Field( - default=None, - sa_column=Column( - DateTime, - nullable=True, - comment="删除时间", - ), - ) # 外键 user_id: "int" = Field(foreign_key="users.id", index=True, description="所属用户ID") diff --git a/models/user.py b/models/user.py index 34f9336..2304c12 100644 --- a/models/user.py +++ b/models/user.py @@ -36,35 +36,6 @@ class User(BaseModel, table=True): score: int = Field(default=0, sa_column_kwargs={"server_default": "0"}, description="用户积分") group_expires: Optional[datetime] = Field(default=None, description="当前用户组过期时间") phone: Optional[str] = Field(default=None, max_length=255, unique=True, index=True, description="手机号") - created_at: Optional[datetime] = Field( - default=None, - sa_column=Column( - DateTime, - nullable=False, - server_default=func.now(), - comment="创建时间", - ), - ) - - updated_at: Optional[datetime] = Field( - default=None, - sa_column=Column( - DateTime, - nullable=False, - server_default=func.now(), - onupdate=func.now(), - comment="更新时间", - ), - ) - - delete_at: Optional[datetime] = Field( - default=None, - sa_column=Column( - DateTime, - nullable=True, - comment="删除时间", - ), - ) # 外键 group_id: int = Field(foreign_key="groups.id", index=True, description="所属用户组ID") diff --git a/models/webdav.py b/models/webdav.py index cb3af41..209ac32 100644 --- a/models/webdav.py +++ b/models/webdav.py @@ -1,9 +1,8 @@ # my_project/models/webdav.py -from typing import Optional, TYPE_CHECKING +from typing import TYPE_CHECKING from sqlmodel import Field, Relationship, UniqueConstraint, text, Column, func, DateTime from .base import BaseModel -from datetime import datetime if TYPE_CHECKING: from .user import User @@ -17,35 +16,6 @@ class WebDAV(BaseModel, table=True): root: str = Field(default="/", sa_column_kwargs={"server_default": "'/'"}, description="根目录路径") readonly: bool = Field(default=False, sa_column_kwargs={"server_default": text("false")}, description="是否只读") use_proxy: bool = Field(default=False, sa_column_kwargs={"server_default": text("false")}, description="是否使用代理下载") - created_at: Optional[datetime] = Field( - default=None, - sa_column=Column( - DateTime, - nullable=False, - server_default=func.now(), - comment="创建时间", - ), - ) - - updated_at: Optional[datetime] = Field( - default=None, - sa_column=Column( - DateTime, - nullable=False, - server_default=func.now(), - onupdate=func.now(), - comment="更新时间", - ), - ) - - delete_at: Optional[datetime] = Field( - default=None, - sa_column=Column( - DateTime, - nullable=True, - comment="删除时间", - ), - ) # 外键 user_id: int = Field(foreign_key="users.id", index=True, description="所属用户ID") diff --git a/tests/test_database.py b/tests/test_database.py index 9f852c4..d6e48f7 100644 --- a/tests/test_database.py +++ b/tests/test_database.py @@ -18,11 +18,11 @@ async def db_session(): yield session @pytest.mark.asyncio -async def test_initialize_db(): +async def test_migration(): """测试数据库创建并初始化配置""" from models import migration from models import database await database.init_db(url='sqlite:///:memory:') - await migration.init_default_settings() \ No newline at end of file + await migration.migration() \ No newline at end of file diff --git a/tests/test_db_group.py b/tests/test_db_group.py index 2590d2b..de65961 100644 --- a/tests/test_db_group.py +++ b/tests/test_db_group.py @@ -3,11 +3,13 @@ import pytest @pytest.mark.asyncio async def test_group_curd(): """测试数据库的增删改查""" - from models import database + from models import database, migration from models.group import Group await database.init_db(url='sqlite:///:memory:') + await migration.migration() + # 测试增 Create test_group = Group(name='test_group') created_group = await Group.create(test_group) diff --git a/tests/test_db_user.py b/tests/test_db_user.py index fec7f04..e2a3be3 100644 --- a/tests/test_db_user.py +++ b/tests/test_db_user.py @@ -3,12 +3,14 @@ import pytest @pytest.mark.asyncio async def test_user_curd(): """测试数据库的增删改查""" - from models import database + from models import database, migration from models.group import Group from models.user import User await database.init_db(url='sqlite:///:memory:') + await migration.migration() + # 新建一个测试用户组 test_user_group = Group(name='test_user_group') created_group = await Group.create(test_user_group)