优化数据库表的创建与检查

This commit is contained in:
?..濡.. 2025-01-04 01:13:47 +08:00
parent ecf90fec31
commit 173580c0af
12 changed files with 1677 additions and 199 deletions

294
README.md
View File

@ -76,178 +76,127 @@ alembic revision --autogenerate -m "Initial migration"
alembic upgrade head
```
## 添加数据库表
## 数据库管理
### 1.创建模型文件:
### 添加新的数据库表
**因为表格太多可以把同类型表放在同一个文件文件命名规则ims_account_wechats、ims_account_wxapp、ims_account_xzapp等表格去除前缀和后缀即为account.py**
1. 创建模型文件:
将同类型的表模型放在同一个文件中。文件命名规则:去除表名的 `ims_` 前缀,例如:
- `ims_account_wechats`、`ims_account_wxapp` 等表 → `account.py`
- `ims_uni_account`、`ims_uni_settings` 等表 → `uni_account.py`
```python
# 这个模型类AccountWechats用于映射ims_account_wechats表
# 1. 在ORM层中代表数据库表结构方便CRUD操作。
# 2. 在FastAPI中引用该模型时可以使用Pydantic自动转换ORM对象到响应模型。
# 3. 创建模型时需确保表名(__tablename__)与真实的数据库表名保持一致,否则查询和插入可能失败。
# 4. 字段类型要与数据库中定义的列类型严格匹配,避免出现不兼容或异常。
# 5. 通过Primary Keyacid唯一标识记录确保ORM能正确追踪和更新该对象。
# 6. config.orm_mode = True允许直接把SQLAlchemy模型实例转换为Pydantic模型对象。
# filepath: ExamService/mooc/models/account.py
# filepath: mooc/models/account.py
from sqlalchemy import Column, Integer, String, SmallInteger
from mooc.db.database import Base
# 类名命名规则: 去除ims前缀后采用 帕斯卡命名法,无连接符每个单词手写大写
# AccountWechats模型用于映射数据库表 ims_account_wechats
class AccountWechats(Base):
__tablename__ = "ims_account_wechats"
class AccountWechats(Base):
"""微信公众号账号表"""
__tablename__ = "ims_account_wechats"
acid = Column(Integer, primary_key=True)
uniacid = Column(Integer, nullable=False)
token = Column(String(32), nullable=False)
encodingaeskey = Column(String(255), nullable=False)
level = Column(SmallInteger, nullable=False)
name = Column(String(30), nullable=False)
account = Column(String(30), nullable=False)
original = Column(String(50), nullable=False)
signature = Column(String(100), nullable=False)
country = Column(String(10), nullable=False)
province = Column(String(3), nullable=False)
city = Column(String(15), nullable=False)
username = Column(String(30), nullable=False)
password = Column(String(32), nullable=False)
lastupdate = Column(Integer, nullable=False)
key = Column(String(50), nullable=False)
secret = Column(String(50), nullable=False)
styleid = Column(Integer, nullable=False)
subscribeurl = Column(String(120), nullable=False)
auth_refresh_token = Column(String(255), nullable=False)
class Config:
from_attributes = True # 允许与Pydantic的ORM功能兼容直接读取数据库模型对象
# ... 其他字段
```
### 2.创建schema:
```python
# filepath: ExamService/mooc/schemas/account.py
2. 在 `mooc/models/__init__.py` 中注册表:
```python
# 添加到 expected_tables 集合中
expected_tables = {
# ... 现有表 ...
'ims_account_wechats', # 新添加的表
}
```
3. 导出模型类:
```python
# 在 mooc/models/__init__.py 中添加导出
from mooc.models.account import AccountWechats
```
4. 创建 Schema:
```python
# filepath: mooc/schemas/account.py
from pydantic import BaseModel
from typing import Optional
class AccountWechatsBase(BaseModel):
"""
数据模型基类: AccountWechatsBase
用于描述基础字段的类型、用途和注意点。
- 注意: 必填字段都在这里声明,每个字段都对应数据库中的一列。
"""
uniacid: int # 微信公众号/小程序的关联ID
token: str # 访问接口时使用的token
encodingaeskey: str # 用于消息加解密的AES密钥
level: int # 认证等级,如订阅号/服务号
name: str # 微信公众号名称
account: str # 公众号帐号,如微信号
original: str # 原始ID(通常以gh_开头)
signature: str # 公众号信息签名
country: str # 国家
province: str # 省份
city: str # 城市
username: str # 后台登录用户名
password: str # 后台登录密码
lastupdate: int # 最后一次更新的时间戳
key: str # 开发者Key
secret: str # 开发者Secret
styleid: int # 模板样式ID
subscribeurl: str # 订阅链接
auth_refresh_token: str # 用来刷新授权的token
uniacid: int
# ... 其他字段
class AccountWechatsCreate(AccountWechatsBase):
"""
用于创建新微信帐号记录:
- 继承自AccountWechatsBase, 不额外添加字段
- 仅表示此Schema专用于'创建'场景
"""
# 用于创建新记录,包含所有必填字段
pass
class AccountWechatsUpdate(BaseModel):
"""
用于更新已有微信帐号记录:
- 只包含可选字段,未在此处的内容将保持不变
- 注意: exclude_unset=True 可以避免更新空值
"""
token: Optional[str] # 可选更新token
encodingaeskey: Optional[str]# 可选更新AES key
class AccountWechats(AccountWechatsBase):
"""
表示完整的微信帐号记录:
- acid: 数据库主键ID
- 包含所有字段的最终模型ORM转换时使用
"""
acid: int # 表中的主键ID
# 可选字段用于更新
uniacid: Optional[int] = None
class AccountWechatsRead(AccountWechatsBase):
acid: int
class Config:
from_attributes = True # 允许与ORM对象进行直接转换
from_attributes = True
```
### 3.创建 CRUD:
```python
# filepath: ExamService/mooc/crud/crud_account.py
from typing import Optional
from sqlalchemy.orm import Session
5. 创建 CRUD 操作:
```python
# filepath: mooc/crud/crud_account.py
from mooc.crud.crud_base import CRUDBase
from mooc.models.account import AccountWechats
from mooc.schemas.account import AccountWechatsCreate, AccountWechatsUpdate
class CRUDAccountWechats(CRUDBase[AccountWechats, AccountWechatsCreate, AccountWechatsUpdate]):
"""
AccountWechats的CRUD操作类
继承自CRUDBase基类实现基础的增删改查功能
可以根据需要添加自定义的查询方法
"""
def get_by_uniacid(self, db: Session, *, uniacid: int) -> Optional[AccountWechats]:
"""
根据uniacid查询微信公众号账号
:param db: 数据库会话
:param uniacid: 统一公众号ID
:return: AccountWechats对象或None
"""
return db.query(self.model).filter(self.model.uniacid == uniacid).first()
return self.get_by_field(db, "uniacid", uniacid)
# 实例化CRUD对象方便在其他地方直接导入使用
# 创建实例
account_wechats = CRUDAccountWechats(AccountWechats)
# 使用示例:
"""
# 创建新记录
new_account = account_wechats.create(db, obj_in=account_create_schema)
# 根据ID获取记录
account = account_wechats.get(db, id=1)
# 根据uniacid获取记录
account = account_wechats.get_by_uniacid(db, uniacid=100)
# 更新记录
updated = account_wechats.update(db, db_obj=existing_account, obj_in=update_data)
# 删除记录
account_wechats.remove(db, id=1)
"""
```
### 4.注册模型:
6. 添加 API 路由:
```python
# filepath: ExamService/mooc/db/base.py
from mooc.db.database import Base
from mooc.models.admin import Admin, Account, AccountWebapp
from mooc.models.account import AccountWechats # 新增,将创建好的模型类导入即可
# filepath: mooc/api/v1/endpoints/account.py
@account_router.post("/wechats", response_model=AccountWechatsRead)
def create_wechat_account(
*,
db: Session = Depends(deps.get_db),
account_in: AccountWechatsCreate,
):
"""创建微信公众号账号"""
return account_wechats.create(db=db, obj_in=account_in)
```
### 5.运行代码更新数据库信息
### 数据库表自动创建
应用启动时会自动执行以下操作:
1. 导入并验证所有模型定义
2. 检查数据库中缺失的表
3. 自动创建缺失的表
你可以通过查看应用日志了解表创建的详细情况:
```bash
python main.py
```
### 注意事项
1. 模型类名采用帕斯卡命名法PascalCase去除 `ims_` 前缀
2. 表名(`__tablename__`)必须与数据库中的实际表名完全一致
3. 字段类型要与数据库定义严格匹配
4. 确保主键和索引的正确定义
5. 添加适当的文档字符串说明表的用途
### 调试帮助
如果遇到问题,可以:
1. 检查日志输出了解具体错误
2. 使用 `get_all_table_names()` 查看已注册的表
3. 验证模型定义是否完整
4. 确认数据库连接配置是否正确
## CRUDBase 使用指南
### 简介
@ -316,3 +265,82 @@ class CRUDYourModel(CRUDBase[YourModel, YourCreateSchema, YourUpdateSchema]):
## API文档
启动服务后访问: http://localhost:2333/docs
### 使用 AI 生成模型代码
当你有一个新的数据库表需要添加时,可以使用以下方式让 AI 帮助生成代码:
1. 准备 SQL 建表语句,例如:
```sql
CREATE TABLE `ims_uni_settings` (
`uniacid` int(10) UNSIGNED NOT NULL,
`passport` varchar(200) NOT NULL,
`oauth` varchar(100) NOT NULL,
-- ... 其他字段
PRIMARY KEY (`uniacid`)
) ENGINE = MyISAM CHARACTER SET = utf8 COLLATE = utf8_general_ci;
```
2. 使用以下提示词模板:
```
请帮我为这个表生成 FastAPI + SQLAlchemy 的实现,包括:
1. SQLAlchemy 模型models/xxx.py
2. Pydantic Schemaschemas/xxx.py
3. CRUD 操作crud/crud_xxx.py
4. API 路由api/v1/endpoints/xxx.py
要求:
- 遵循项目的命名规范去除ims_前缀使用帕斯卡命名法
- 确保字段类型映射正确
- 包含必要的文档注释
- 实现基本的 CRUD 操作和常用查询方法
[SQL建表语句]
```
3. 对生成的代码进行以下检查:
- 表名是否与数据库一致
- 字段类型是否正确映射
- 主键和索引是否正确定义
- 是否符合项目的命名规范
- CRUD 方法是否满足业务需求
4. 常用的 SQL 类型映射参考:
```python
# MySQL 到 SQLAlchemy 的类型映射
int/bigint -> Integer
varchar/char -> String(length)
text -> Text
datetime -> DateTime
timestamp -> TIMESTAMP
tinyint -> SmallInteger
decimal -> DECIMAL(precision, scale)
```
5. 示例提示词:
```
我需要为以下数据表生成 FastAPI 实现:
- 表名ims_uni_settings
- 主键uniacid
- 特殊需求:
* 需要通过 uniacid 查询的方法
* 需要处理 Text 类型的 payment 字段
* 所有字符串字段都是必填的
[SQL语句]
...
请生成完整的代码实现。
```
6. 代码生成后的集成步骤:
- 将模型类添加到对应的 models 文件
- 在 models/__init__.py 中注册表名
- 在 api.py 中注册新的路由
- 检查并测试生成的 API 端点
这种方式可以:
- 快速生成符合项目规范的代码
- 确保类型映射的准确性
- 保持代码结构的一致性
- 减少手动编码的错误

View File

@ -1,9 +1,8 @@
from fastapi import APIRouter
from mooc.api.v1.endpoints import admin, wechat, account
from mooc.api.v1.endpoints import admin, wechat, account, uni_account
api_router = APIRouter()
# עԱ·ɣǰ׺Ϊ/admins
api_router.include_router(
admin.admin_router,
prefix="/admins",
@ -24,4 +23,12 @@ api_router.include_router(
)
# Add WeChat endpoints
api_router.include_router(wechat.router, prefix="/wechat", tags=["wechat"])
api_router.include_router(wechat.router, prefix="/wechat", tags=["wechat"])
api_router.include_router(
uni_account.uni_account_router,
prefix="/uni-accounts",
tags=["uni-accounts"]
)

View File

@ -0,0 +1,682 @@
from typing import List
from fastapi import APIRouter, Depends, HTTPException
from sqlalchemy.orm import Session
from mooc.api import deps
from mooc.crud.crud_uni_account import (
uni_account, uni_account_extra_modules,
uni_account_group, uni_account_menus,
uni_account_modules, uni_account_modules_shortcut,
uni_account_users, uni_group,
uni_link_uniacid, uni_modules,
uni_verifycode, uni_settings
)
from mooc.schemas.uni_account import (
UniAccountCreate,
UniAccountRead,
UniAccountUpdate,
UniAccountExtraModulesCreate,
UniAccountExtraModulesRead,
UniAccountExtraModulesUpdate,
UniAccountGroupCreate,
UniAccountGroupRead,
UniAccountGroupUpdate,
UniAccountMenusCreate,
UniAccountMenusRead,
UniAccountMenusUpdate,
UniAccountModulesCreate,
UniAccountModulesRead,
UniAccountModulesUpdate,
UniAccountModulesShortcutCreate,
UniAccountModulesShortcutRead,
UniAccountModulesShortcutUpdate,
UniAccountUsersCreate,
UniAccountUsersRead,
UniAccountUsersUpdate,
UniGroupCreate,
UniGroupRead,
UniGroupUpdate,
UniLinkUniacidCreate,
UniLinkUniacidRead,
UniLinkUniacidUpdate,
UniModulesCreate,
UniModulesRead,
UniModulesUpdate,
UniVerifycodeCreate,
UniVerifycodeRead,
UniVerifycodeUpdate,
UniSettingsCreate,
UniSettingsRead,
UniSettingsUpdate
)
uni_account_router = APIRouter()
# UniAccount 路由
@uni_account_router.post("/", response_model=UniAccountRead)
def create_uni_account(
*,
db: Session = Depends(deps.get_db),
uni_account_in: UniAccountCreate,
):
"""
创建统一公众号账户
"""
return uni_account.create(db=db, obj_in=uni_account_in)
@uni_account_router.get("/{uniacid}", response_model=UniAccountRead)
def read_uni_account(
*,
db: Session = Depends(deps.get_db),
uniacid: int,
):
"""
获取统一公众号账户信息
"""
db_uni_account = uni_account.get(db=db, id=uniacid)
if not db_uni_account:
raise HTTPException(
status_code=404,
detail="UniAccount not found"
)
return db_uni_account
@uni_account_router.put("/{uniacid}", response_model=UniAccountRead)
def update_uni_account(
*,
db: Session = Depends(deps.get_db),
uniacid: int,
uni_account_in: UniAccountUpdate,
):
"""
更新统一公众号账户信息
"""
db_uni_account = uni_account.get(db=db, id=uniacid)
if not db_uni_account:
raise HTTPException(
status_code=404,
detail="UniAccount not found"
)
return uni_account.update(db=db, db_obj=db_uni_account, obj_in=uni_account_in)
@uni_account_router.delete("/{uniacid}", response_model=UniAccountRead)
def delete_uni_account(
*,
db: Session = Depends(deps.get_db),
uniacid: int,
):
"""
删除统一公众号账户
"""
db_uni_account = uni_account.get(db=db, id=uniacid)
if not db_uni_account:
raise HTTPException(
status_code=404,
detail="UniAccount not found"
)
return uni_account.delete(db=db, id=uniacid)
# UniAccountExtraModules 路由
@uni_account_router.post("/modules", response_model=UniAccountExtraModulesRead)
def create_extra_modules(
*,
db: Session = Depends(deps.get_db),
modules_in: UniAccountExtraModulesCreate,
):
"""
创建账户额外模块
"""
return uni_account_extra_modules.create(db=db, obj_in=modules_in)
@uni_account_router.get("/modules/{id}", response_model=UniAccountExtraModulesRead)
def read_extra_modules(
*,
db: Session = Depends(deps.get_db),
id: int,
):
"""
获取账户额外模块信息
"""
db_modules = uni_account_extra_modules.get(db=db, id=id)
if not db_modules:
raise HTTPException(
status_code=404,
detail="Extra modules not found"
)
return db_modules
@uni_account_router.get("/modules/by-uniacid/{uniacid}", response_model=UniAccountExtraModulesRead)
def read_extra_modules_by_uniacid(
*,
db: Session = Depends(deps.get_db),
uniacid: int,
):
"""
通过uniacid获取账户额外模块信息
"""
db_modules = uni_account_extra_modules.get_by_uniacid(db=db, uniacid=uniacid)
if not db_modules:
raise HTTPException(
status_code=404,
detail="Extra modules not found"
)
return db_modules
@uni_account_router.put("/modules/{id}", response_model=UniAccountExtraModulesRead)
def update_extra_modules(
*,
db: Session = Depends(deps.get_db),
id: int,
modules_in: UniAccountExtraModulesUpdate,
):
"""
更新账户额外模块信息
"""
db_modules = uni_account_extra_modules.get(db=db, id=id)
if not db_modules:
raise HTTPException(
status_code=404,
detail="Extra modules not found"
)
return uni_account_extra_modules.update(db=db, db_obj=db_modules, obj_in=modules_in)
@uni_account_router.delete("/modules/{id}", response_model=UniAccountExtraModulesRead)
def delete_extra_modules(
*,
db: Session = Depends(deps.get_db),
id: int,
):
"""
删除账户额外模块
"""
db_modules = uni_account_extra_modules.get(db=db, id=id)
if not db_modules:
raise HTTPException(
status_code=404,
detail="Extra modules not found"
)
return uni_account_extra_modules.delete(db=db, id=id)
# UniAccountGroup 路由
@uni_account_router.post("/groups", response_model=UniAccountGroupRead)
def create_group(
*,
db: Session = Depends(deps.get_db),
group_in: UniAccountGroupCreate,
):
"""创建账户组关联"""
return uni_account_group.create(db=db, obj_in=group_in)
@uni_account_router.get("/groups/{id}", response_model=UniAccountGroupRead)
def read_group(*, db: Session = Depends(deps.get_db), id: int):
"""获取账户组关联信息"""
group = uni_account_group.get(db=db, id=id)
if not group:
raise HTTPException(status_code=404, detail="Account group not found")
return group
@uni_account_router.put("/groups/{id}", response_model=UniAccountGroupRead)
def update_group(
*,
db: Session = Depends(deps.get_db),
id: int,
group_in: UniAccountGroupUpdate,
):
"""更新账户组关联信息"""
group = uni_account_group.get(db=db, id=id)
if not group:
raise HTTPException(status_code=404, detail="Account group not found")
return uni_account_group.update(db=db, db_obj=group, obj_in=group_in)
@uni_account_router.delete("/groups/{id}", response_model=UniAccountGroupRead)
def delete_group(*, db: Session = Depends(deps.get_db), id: int):
"""删除账户组关联"""
group = uni_account_group.get(db=db, id=id)
if not group:
raise HTTPException(status_code=404, detail="Account group not found")
return uni_account_group.delete(db=db, id=id)
# UniAccountMenus 路由
@uni_account_router.post("/menus", response_model=UniAccountMenusRead)
def create_menu(
*,
db: Session = Depends(deps.get_db),
menu_in: UniAccountMenusCreate,
):
"""创建账户菜单"""
return uni_account_menus.create(db=db, obj_in=menu_in)
@uni_account_router.get("/menus/{id}", response_model=UniAccountMenusRead)
def read_menu(*, db: Session = Depends(deps.get_db), id: int):
"""获取账户菜单信息"""
menu = uni_account_menus.get(db=db, id=id)
if not menu:
raise HTTPException(status_code=404, detail="Account menu not found")
return menu
@uni_account_router.get("/menus/by-uniacid/{uniacid}", response_model=UniAccountMenusRead)
def read_menu_by_uniacid(*, db: Session = Depends(deps.get_db), uniacid: int):
"""通过uniacid获取账户菜单信息"""
menu = uni_account_menus.get_by_uniacid(db=db, uniacid=uniacid)
if not menu:
raise HTTPException(status_code=404, detail="Account menu not found")
return menu
@uni_account_router.put("/menus/{id}", response_model=UniAccountMenusRead)
def update_menu(
*,
db: Session = Depends(deps.get_db),
id: int,
menu_in: UniAccountMenusUpdate,
):
"""更新账户菜单信息"""
menu = uni_account_menus.get(db=db, id=id)
if not menu:
raise HTTPException(status_code=404, detail="Account menu not found")
return uni_account_menus.update(db=db, db_obj=menu, obj_in=menu_in)
@uni_account_router.delete("/menus/{id}", response_model=UniAccountMenusRead)
def delete_menu(*, db: Session = Depends(deps.get_db), id: int):
"""删除账户菜单"""
menu = uni_account_menus.get(db=db, id=id)
if not menu:
raise HTTPException(status_code=404, detail="Account menu not found")
return uni_account_menus.delete(db=db, id=id)
# UniAccountModules 路由
@uni_account_router.post("/modules", response_model=UniAccountModulesRead)
def create_module(
*,
db: Session = Depends(deps.get_db),
module_in: UniAccountModulesCreate,
):
"""创建账户模块"""
return uni_account_modules.create(db=db, obj_in=module_in)
@uni_account_router.get("/modules/{id}", response_model=UniAccountModulesRead)
def read_module(*, db: Session = Depends(deps.get_db), id: int):
"""获取账户模块信息"""
module = uni_account_modules.get(db=db, id=id)
if not module:
raise HTTPException(status_code=404, detail="Account module not found")
return module
@uni_account_router.get("/modules/by-uniacid/{uniacid}", response_model=UniAccountModulesRead)
def read_module_by_uniacid(*, db: Session = Depends(deps.get_db), uniacid: int):
"""通过uniacid获取账户模块信息"""
module = uni_account_modules.get_by_uniacid(db=db, uniacid=uniacid)
if not module:
raise HTTPException(status_code=404, detail="Account module not found")
return module
@uni_account_router.put("/modules/{id}", response_model=UniAccountModulesRead)
def update_module(
*,
db: Session = Depends(deps.get_db),
id: int,
module_in: UniAccountModulesUpdate,
):
"""更新账户模块信息"""
module = uni_account_modules.get(db=db, id=id)
if not module:
raise HTTPException(status_code=404, detail="Account module not found")
return uni_account_modules.update(db=db, db_obj=module, obj_in=module_in)
@uni_account_router.delete("/modules/{id}", response_model=UniAccountModulesRead)
def delete_module(*, db: Session = Depends(deps.get_db), id: int):
"""删除账户模块"""
module = uni_account_modules.get(db=db, id=id)
if not module:
raise HTTPException(status_code=404, detail="Account module not found")
return uni_account_modules.delete(db=db, id=id)
# UniAccountModulesShortcut 完整路由
@uni_account_router.post("/modules-shortcut", response_model=UniAccountModulesShortcutRead)
def create_module_shortcut(
*,
db: Session = Depends(deps.get_db),
shortcut_in: UniAccountModulesShortcutCreate,
):
"""创建模块快捷方式"""
return uni_account_modules_shortcut.create(db=db, obj_in=shortcut_in)
@uni_account_router.get("/modules-shortcut/{id}", response_model=UniAccountModulesShortcutRead)
def read_module_shortcut(*, db: Session = Depends(deps.get_db), id: int):
"""获取模块快捷方式"""
shortcut = uni_account_modules_shortcut.get(db=db, id=id)
if not shortcut:
raise HTTPException(status_code=404, detail="Module shortcut not found")
return shortcut
@uni_account_router.get("/modules-shortcut/by-uniacid/{uniacid}", response_model=UniAccountModulesShortcutRead)
def read_module_shortcut_by_uniacid(*, db: Session = Depends(deps.get_db), uniacid: int):
"""通过uniacid获取模块快捷方式"""
shortcut = uni_account_modules_shortcut.get_by_uniacid(db=db, uniacid=uniacid)
if not shortcut:
raise HTTPException(status_code=404, detail="Module shortcut not found")
return shortcut
@uni_account_router.put("/modules-shortcut/{id}", response_model=UniAccountModulesShortcutRead)
def update_module_shortcut(
*,
db: Session = Depends(deps.get_db),
id: int,
shortcut_in: UniAccountModulesShortcutUpdate,
):
"""更新模块快捷方式"""
shortcut = uni_account_modules_shortcut.get(db=db, id=id)
if not shortcut:
raise HTTPException(status_code=404, detail="Module shortcut not found")
return uni_account_modules_shortcut.update(db=db, db_obj=shortcut, obj_in=shortcut_in)
@uni_account_router.delete("/modules-shortcut/{id}", response_model=UniAccountModulesShortcutRead)
def delete_module_shortcut(*, db: Session = Depends(deps.get_db), id: int):
"""删除模块快捷方式"""
shortcut = uni_account_modules_shortcut.get(db=db, id=id)
if not shortcut:
raise HTTPException(status_code=404, detail="Module shortcut not found")
return uni_account_modules_shortcut.delete(db=db, id=id)
# UniAccountUsers 完整路由
@uni_account_router.post("/users", response_model=UniAccountUsersRead)
def create_account_user(
*,
db: Session = Depends(deps.get_db),
user_in: UniAccountUsersCreate,
):
"""创建账户用户关联"""
return uni_account_users.create(db=db, obj_in=user_in)
@uni_account_router.get("/users/{id}", response_model=UniAccountUsersRead)
def read_account_user(*, db: Session = Depends(deps.get_db), id: int):
"""获取账户用户关联信息"""
user = uni_account_users.get(db=db, id=id)
if not user:
raise HTTPException(status_code=404, detail="Account user not found")
return user
@uni_account_router.get("/users/by-uniacid/{uniacid}", response_model=UniAccountUsersRead)
def read_account_user_by_uniacid(*, db: Session = Depends(deps.get_db), uniacid: int):
"""通过uniacid获取账户用户关联信息"""
user = uni_account_users.get_by_uniacid(db=db, uniacid=uniacid)
if not user:
raise HTTPException(status_code=404, detail="Account user not found")
return user
@uni_account_router.get("/users/by-uid/{uid}", response_model=UniAccountUsersRead)
def read_account_user_by_uid(*, db: Session = Depends(deps.get_db), uid: int):
"""通过uid获取账户用户关联信息"""
user = uni_account_users.get_by_uid(db=db, uid=uid)
if not user:
raise HTTPException(status_code=404, detail="Account user not found")
return user
@uni_account_router.put("/users/{id}", response_model=UniAccountUsersRead)
def update_account_user(
*,
db: Session = Depends(deps.get_db),
id: int,
user_in: UniAccountUsersUpdate,
):
"""更新账户用户关联信息"""
user = uni_account_users.get(db=db, id=id)
if not user:
raise HTTPException(status_code=404, detail="Account user not found")
return uni_account_users.update(db=db, db_obj=user, obj_in=user_in)
@uni_account_router.delete("/users/{id}", response_model=UniAccountUsersRead)
def delete_account_user(*, db: Session = Depends(deps.get_db), id: int):
"""删除账户用户关联"""
user = uni_account_users.get(db=db, id=id)
if not user:
raise HTTPException(status_code=404, detail="Account user not found")
return uni_account_users.delete(db=db, id=id)
# UniGroup 完整路由
@uni_account_router.post("/groups", response_model=UniGroupRead)
def create_uni_group(
*,
db: Session = Depends(deps.get_db),
group_in: UniGroupCreate,
):
"""创建统一公众号组"""
return uni_group.create(db=db, obj_in=group_in)
@uni_account_router.get("/groups/{id}", response_model=UniGroupRead)
def read_uni_group(*, db: Session = Depends(deps.get_db), id: int):
"""获取统一公众号组信息"""
group = uni_group.get(db=db, id=id)
if not group:
raise HTTPException(status_code=404, detail="Uni group not found")
return group
@uni_account_router.get("/groups/by-uniacid/{uniacid}", response_model=UniGroupRead)
def read_uni_group_by_uniacid(*, db: Session = Depends(deps.get_db), uniacid: int):
"""通过uniacid获取统一公众号组信息"""
group = uni_group.get_by_uniacid(db=db, uniacid=uniacid)
if not group:
raise HTTPException(status_code=404, detail="Uni group not found")
return group
@uni_account_router.get("/groups/by-owner/{owner_uid}", response_model=UniGroupRead)
def read_uni_group_by_owner(*, db: Session = Depends(deps.get_db), owner_uid: int):
"""通过owner_uid获取统一公众号组信息"""
group = uni_group.get_by_owner(db=db, owner_uid=owner_uid)
if not group:
raise HTTPException(status_code=404, detail="Uni group not found")
return group
@uni_account_router.put("/groups/{id}", response_model=UniGroupRead)
def update_uni_group(
*,
db: Session = Depends(deps.get_db),
id: int,
group_in: UniGroupUpdate,
):
"""更新统一公众号组信息"""
group = uni_group.get(db=db, id=id)
if not group:
raise HTTPException(status_code=404, detail="Uni group not found")
return uni_group.update(db=db, db_obj=group, obj_in=group_in)
@uni_account_router.delete("/groups/{id}", response_model=UniGroupRead)
def delete_uni_group(*, db: Session = Depends(deps.get_db), id: int):
"""删除统一公众号组"""
group = uni_group.get(db=db, id=id)
if not group:
raise HTTPException(status_code=404, detail="Uni group not found")
return uni_group.delete(db=db, id=id)
# UniLinkUniacid 路由
@uni_account_router.post("/links", response_model=UniLinkUniacidRead)
def create_link_uniacid(
*,
db: Session = Depends(deps.get_db),
link_in: UniLinkUniacidCreate,
):
"""创建公众号链接关系"""
return uni_link_uniacid.create(db=db, obj_in=link_in)
@uni_account_router.get("/links/{id}", response_model=UniLinkUniacidRead)
def read_link_uniacid(*, db: Session = Depends(deps.get_db), id: int):
"""获取公众号链接关系"""
link = uni_link_uniacid.get(db=db, id=id)
if not link:
raise HTTPException(status_code=404, detail="Link uniacid not found")
return link
@uni_account_router.get("/links/by-uniacid/{uniacid}", response_model=UniLinkUniacidRead)
def read_link_uniacid_by_uniacid(*, db: Session = Depends(deps.get_db), uniacid: int):
"""通过uniacid获取公众号链接关系"""
link = uni_link_uniacid.get_by_uniacid(db=db, uniacid=uniacid)
if not link:
raise HTTPException(status_code=404, detail="Link uniacid not found")
return link
@uni_account_router.put("/links/{id}", response_model=UniLinkUniacidRead)
def update_link_uniacid(
*,
db: Session = Depends(deps.get_db),
id: int,
link_in: UniLinkUniacidUpdate,
):
"""更新公众号链接关系"""
link = uni_link_uniacid.get(db=db, id=id)
if not link:
raise HTTPException(status_code=404, detail="Link uniacid not found")
return uni_link_uniacid.update(db=db, db_obj=link, obj_in=link_in)
@uni_account_router.delete("/links/{id}", response_model=UniLinkUniacidRead)
def delete_link_uniacid(*, db: Session = Depends(deps.get_db), id: int):
"""删除公众号链接关系"""
link = uni_link_uniacid.get(db=db, id=id)
if not link:
raise HTTPException(status_code=404, detail="Link uniacid not found")
return uni_link_uniacid.delete(db=db, id=id)
# UniModules 路由
@uni_account_router.post("/uni-modules", response_model=UniModulesRead)
def create_uni_module(
*,
db: Session = Depends(deps.get_db),
module_in: UniModulesCreate,
):
"""创建统一模块"""
return uni_modules.create(db=db, obj_in=module_in)
@uni_account_router.get("/uni-modules/{id}", response_model=UniModulesRead)
def read_uni_module(*, db: Session = Depends(deps.get_db), id: int):
"""获取统一模块信息"""
module = uni_modules.get(db=db, id=id)
if not module:
raise HTTPException(status_code=404, detail="Uni module not found")
return module
@uni_account_router.get("/uni-modules/by-uniacid/{uniacid}", response_model=UniModulesRead)
def read_uni_module_by_uniacid(*, db: Session = Depends(deps.get_db), uniacid: int):
"""通过uniacid获取统一模块信息"""
module = uni_modules.get_by_uniacid(db=db, uniacid=uniacid)
if not module:
raise HTTPException(status_code=404, detail="Uni module not found")
return module
@uni_account_router.put("/uni-modules/{id}", response_model=UniModulesRead)
def update_uni_module(
*,
db: Session = Depends(deps.get_db),
id: int,
module_in: UniModulesUpdate,
):
"""更新统一模块信息"""
module = uni_modules.get(db=db, id=id)
if not module:
raise HTTPException(status_code=404, detail="Uni module not found")
return uni_modules.update(db=db, db_obj=module, obj_in=module_in)
@uni_account_router.delete("/uni-modules/{id}", response_model=UniModulesRead)
def delete_uni_module(*, db: Session = Depends(deps.get_db), id: int):
"""删除统一模块"""
module = uni_modules.get(db=db, id=id)
if not module:
raise HTTPException(status_code=404, detail="Uni module not found")
return uni_modules.delete(db=db, id=id)
# UniVerifycode 路由
@uni_account_router.post("/verifycodes", response_model=UniVerifycodeRead)
def create_verifycode(
*,
db: Session = Depends(deps.get_db),
verifycode_in: UniVerifycodeCreate,
):
"""创建验证码"""
return uni_verifycode.create(db=db, obj_in=verifycode_in)
@uni_account_router.get("/verifycodes/{id}", response_model=UniVerifycodeRead)
def read_verifycode(*, db: Session = Depends(deps.get_db), id: int):
"""获取验证码信息"""
verifycode = uni_verifycode.get(db=db, id=id)
if not verifycode:
raise HTTPException(status_code=404, detail="Verifycode not found")
return verifycode
@uni_account_router.get("/verifycodes/by-uniacid/{uniacid}", response_model=UniVerifycodeRead)
def read_verifycode_by_uniacid(*, db: Session = Depends(deps.get_db), uniacid: int):
"""通过uniacid获取验证码信息"""
verifycode = uni_verifycode.get_by_uniacid(db=db, uniacid=uniacid)
if not verifycode:
raise HTTPException(status_code=404, detail="Verifycode not found")
return verifycode
@uni_account_router.get("/verifycodes/by-receiver/{receiver}", response_model=UniVerifycodeRead)
def read_verifycode_by_receiver(*, db: Session = Depends(deps.get_db), receiver: str):
"""通过接收者获取验证码信息"""
verifycode = uni_verifycode.get_by_receiver(db=db, receiver=receiver)
if not verifycode:
raise HTTPException(status_code=404, detail="Verifycode not found")
return verifycode
@uni_account_router.put("/verifycodes/{id}", response_model=UniVerifycodeRead)
def update_verifycode(
*,
db: Session = Depends(deps.get_db),
id: int,
verifycode_in: UniVerifycodeUpdate,
):
"""更新验证码信息"""
verifycode = uni_verifycode.get(db=db, id=id)
if not verifycode:
raise HTTPException(status_code=404, detail="Verifycode not found")
return uni_verifycode.update(db=db, db_obj=verifycode, obj_in=verifycode_in)
@uni_account_router.delete("/verifycodes/{id}", response_model=UniVerifycodeRead)
def delete_verifycode(*, db: Session = Depends(deps.get_db), id: int):
"""删除验证码"""
verifycode = uni_verifycode.get(db=db, id=id)
if not verifycode:
raise HTTPException(status_code=404, detail="Verifycode not found")
return uni_verifycode.delete(db=db, id=id)
# UniSettings 路由
@uni_account_router.post("/settings", response_model=UniSettingsRead)
def create_settings(
*,
db: Session = Depends(deps.get_db),
settings_in: UniSettingsCreate,
):
"""创建公众号设置"""
# 检查是否已存在该uniacid的设置
existing_settings = uni_settings.get_by_uniacid(db=db, uniacid=settings_in.uniacid)
if existing_settings:
raise HTTPException(
status_code=400,
detail="Settings for this uniacid already exists"
)
return uni_settings.create_with_uniacid(db=db, obj_in=settings_in)
@uni_account_router.get("/settings/{uniacid}", response_model=UniSettingsRead)
def read_settings(*, db: Session = Depends(deps.get_db), uniacid: int):
"""获取公众号设置"""
settings = uni_settings.get_by_uniacid(db=db, uniacid=uniacid)
if not settings:
raise HTTPException(status_code=404, detail="Settings not found")
return settings
@uni_account_router.put("/settings/{uniacid}", response_model=UniSettingsRead)
def update_settings(
*,
db: Session = Depends(deps.get_db),
uniacid: int,
settings_in: UniSettingsUpdate,
):
"""更新公众号设置"""
settings = uni_settings.get_by_uniacid(db=db, uniacid=uniacid)
if not settings:
raise HTTPException(status_code=404, detail="Settings not found")
return uni_settings.update(db=db, db_obj=settings, obj_in=settings_in)
@uni_account_router.delete("/settings/{uniacid}", response_model=UniSettingsRead)
def delete_settings(*, db: Session = Depends(deps.get_db), uniacid: int):
"""删除公众号设置"""
settings = uni_settings.get_by_uniacid(db=db, uniacid=uniacid)
if not settings:
raise HTTPException(status_code=404, detail="Settings not found")
return uni_settings.delete(db=db, id=uniacid)

View File

@ -19,42 +19,37 @@ from mooc.schemas.account import (
class CRUDAccountWechats(CRUDBase[AccountWechats, AccountWechatsCreate, AccountWechatsUpdate]):
def get_by_uniacid(self, db: Session, *, uniacid: int) -> Optional[AccountWechats]:
return db.query(self.model).filter(self.model.uniacid == uniacid).first()
return self.get_by_field(db, "uniacid", uniacid)
class CRUDAccountAliapp(CRUDBase[AccountAliapp, AccountAliappCreate, AccountAliappUpdate]):
def get_by_uniacid(self, db: Session, *, uniacid: int) -> Optional[AccountAliapp]:
return db.query(self.model).filter(self.model.uniacid == uniacid).first()
return self.get_by_field(db, "uniacid", uniacid)
class CRUDAccountBaiduapp(CRUDBase[AccountBaiduapp, AccountBaiduappCreate, AccountBaiduappUpdate]):
def get_by_uniacid(self, db: Session, *, uniacid: int) -> Optional[AccountBaiduapp]:
return db.query(self.model).filter(self.model.uniacid == uniacid).first()
return self.get_by_field(db, "uniacid", uniacid)
class CRUDAccountPhoneapp(CRUDBase[AccountPhoneapp, AccountPhoneappCreate, AccountPhoneappUpdate]):
def get_by_uniacid(self, db: Session, *, uniacid: int) -> Optional[AccountPhoneapp]:
return db.query(self.model).filter(self.model.uniacid == uniacid).first()
return self.get_by_field(db, "uniacid", uniacid)
class CRUDAccountToutiaoapp(CRUDBase[AccountToutiaoapp, AccountToutiaoappCreate, AccountToutiaoappUpdate]):
def get_by_uniacid(self, db: Session, *, uniacid: int) -> Optional[AccountToutiaoapp]:
return db.query(self.model).filter(self.model.uniacid == uniacid).first()
return self.get_by_field(db, "uniacid", uniacid)
class CRUDAccountWebapp(CRUDBase[AccountWebapp, AccountWebappCreate, AccountWebappUpdate]):
def get_by_uniacid(self, db: Session, *, uniacid: int) -> Optional[AccountWebapp]:
return db.query(self.model).filter(self.model.uniacid == uniacid).first()
return self.get_by_field(db, "uniacid", uniacid)
class CRUDAccountWxapp(CRUDBase[AccountWxapp, AccountWxappCreate, AccountWxappUpdate]):
def get_by_uniacid(self, db: Session, *, uniacid: int) -> Optional[AccountWxapp]:
return db.query(self.model).filter(self.model.uniacid == uniacid).first()
return self.get_by_field(db, "uniacid", uniacid)
class CRUDAccountXzapp(CRUDBase[AccountXzapp, AccountXzappCreate, AccountXzappUpdate]):
def get_by_uniacid(self, db: Session, *, uniacid: int) -> Optional[AccountXzapp]:
return db.query(self.model).filter(self.model.uniacid == uniacid).first()
return self.get_by_field(db, "uniacid", uniacid)
class CRUDAccount(CRUDBase[Account, None, None]):
def get_by_uniacid(self, db: Session, *, uniacid: int) -> Optional[Account]:
return db.query(self.model).filter(self.model.uniacid == uniacid).first()
# 实例化所有CRUD对象
account = CRUDAccount(Account)
# 创建实例
account_wechats = CRUDAccountWechats(AccountWechats)
account_aliapp = CRUDAccountAliapp(AccountAliapp)
account_baiduapp = CRUDAccountBaiduapp(AccountBaiduapp)

View File

@ -1,54 +1,22 @@
from typing import List, Optional
from typing import Optional
from sqlalchemy.orm import Session
from mooc.crud.crud_base import CRUDBase
from mooc.models.admin import Admin
from mooc.schemas.admin import AdminCreate, AdminUpdate
class CRUDAdmin:
def get(self, db: Session, id: int) -> Optional[Admin]:
return db.query(Admin).filter(Admin.id == id).first()
def get_by_username(self, db: Session, username: str) -> Optional[Admin]:
return db.query(Admin).filter(Admin.username == username).first()
def get_multi(
self, db: Session, *, skip: int = 0, limit: int = 100
) -> List[Admin]:
return db.query(Admin).offset(skip).limit(limit).all()
def create(self, db: Session, *, obj_in: AdminCreate) -> Admin:
db_obj = Admin(
weid=obj_in.weid,
username=obj_in.username,
password=obj_in.password,
pcate_id=obj_in.pcate_id,
cate_id=obj_in.cate_id,
relation_id=obj_in.relation_id,
is_delete=obj_in.is_delete
)
db.add(db_obj)
db.commit()
db.refresh(db_obj)
return db_obj
def update(
self, db: Session, *, db_obj: Admin, obj_in: AdminUpdate
) -> Admin:
update_data = obj_in.dict(exclude_unset=True)
for field, value in update_data.items():
setattr(db_obj, field, value)
db.add(db_obj)
db.commit()
db.refresh(db_obj)
return db_obj
class CRUDAdmin(CRUDBase[Admin, AdminCreate, AdminUpdate]):
def get_by_username(self, db: Session, *, username: str) -> Optional[Admin]:
return self.get_by_field(db, "username", username)
def delete(self, db: Session, *, id: int) -> Admin:
obj = db.query(Admin).get(id)
"""重写删除方法,实现软删除"""
obj = self.get(db, id=id)
if obj:
obj.is_delete = 1
db.add(obj)
db.commit()
db.refresh(obj)
return obj
admin = CRUDAdmin()
admin = CRUDAdmin(Admin)

View File

@ -2,9 +2,10 @@ from typing import Any, Dict, Generic, List, Optional, Type, TypeVar, Union
from fastapi.encoders import jsonable_encoder
from pydantic import BaseModel
from sqlalchemy.orm import Session
from sqlalchemy import Column
from mooc.db.database import Base
ModelType = TypeVar("ModelType", bound=Base)
ModelType = TypeVar("ModelType", bound="Base")
CreateSchemaType = TypeVar("CreateSchemaType", bound=BaseModel)
UpdateSchemaType = TypeVar("UpdateSchemaType", bound=BaseModel)
@ -18,8 +19,46 @@ class CRUDBase(Generic[ModelType, CreateSchemaType, UpdateSchemaType]):
self.model = model
def get(self, db: Session, id: Any) -> Optional[ModelType]:
"""通过主键获取记录"""
return db.query(self.model).filter(self.model.acid == id).first()
def get_by_field(
self,
db: Session,
field: str,
value: Any
) -> Optional[ModelType]:
"""
通过任意字段获取单条记录
Args:
db: 数据库会话
field: 字段名
value: 字段值
"""
return db.query(self.model).filter(getattr(self.model, field) == value).first()
def get_multi_by_field(
self,
db: Session,
field: str,
value: Any,
*,
skip: int = 0,
limit: int = 100
) -> List[ModelType]:
"""
通过任意字段获取多条记录
Args:
db: 数据库会话
field: 字段名
value: 字段值
skip: 跳过记录数
limit: 返回记录数限制
"""
return db.query(self.model).filter(
getattr(self.model, field) == value
).offset(skip).limit(limit).all()
def get_multi(
self, db: Session, *, skip: int = 0, limit: int = 100
) -> List[ModelType]:

View File

@ -0,0 +1,110 @@
from typing import Optional
from sqlalchemy.orm import Session
from mooc.crud.crud_base import CRUDBase
from mooc.models.uni_account import (
UniAccount, UniAccountExtraModules,
UniAccountGroup, UniAccountMenus,
UniAccountModules,
UniAccountModulesShortcut,
UniAccountUsers,
UniGroup,
UniLinkUniacid,
UniModules,
UniVerifycode,
UniSettings
)
from mooc.schemas.uni_account import (
UniAccountCreate, UniAccountUpdate,
UniAccountExtraModulesCreate, UniAccountExtraModulesUpdate,
UniAccountGroupCreate, UniAccountGroupUpdate,
UniAccountMenusCreate, UniAccountMenusUpdate,
UniAccountModulesCreate, UniAccountModulesUpdate,
UniAccountModulesShortcutCreate, UniAccountModulesShortcutUpdate,
UniAccountUsersCreate, UniAccountUsersUpdate,
UniGroupCreate, UniGroupUpdate,
UniLinkUniacidCreate, UniLinkUniacidUpdate,
UniModulesCreate, UniModulesUpdate,
UniVerifycodeCreate, UniVerifycodeUpdate,
UniSettingsCreate, UniSettingsUpdate
)
class CRUDUniAccount(CRUDBase[UniAccount, UniAccountCreate, UniAccountUpdate]):
def get_by_uniacid(self, db: Session, *, uniacid: int) -> Optional[UniAccount]:
return self.get_by_field(db, "uniacid", uniacid)
class CRUDUniAccountExtraModules(CRUDBase[UniAccountExtraModules, UniAccountExtraModulesCreate, UniAccountExtraModulesUpdate]):
def get_by_uniacid(self, db: Session, *, uniacid: int) -> Optional[UniAccountExtraModules]:
return self.get_by_field(db, "uniacid", uniacid)
class CRUDUniAccountGroup(CRUDBase[UniAccountGroup, UniAccountGroupCreate, UniAccountGroupUpdate]):
def get_by_uniacid(self, db: Session, *, uniacid: int) -> Optional[UniAccountGroup]:
return self.get_by_field(db, "uniacid", uniacid)
class CRUDUniAccountMenus(CRUDBase[UniAccountMenus, UniAccountMenusCreate, UniAccountMenusUpdate]):
def get_by_uniacid(self, db: Session, *, uniacid: int) -> Optional[UniAccountMenus]:
return self.get_by_field(db, "uniacid", uniacid)
class CRUDUniAccountModules(CRUDBase[UniAccountModules, UniAccountModulesCreate, UniAccountModulesUpdate]):
def get_by_uniacid(self, db: Session, *, uniacid: int) -> Optional[UniAccountModules]:
return self.get_by_field(db, "uniacid", uniacid)
class CRUDUniAccountModulesShortcut(CRUDBase[UniAccountModulesShortcut, UniAccountModulesShortcutCreate, UniAccountModulesShortcutUpdate]):
def get_by_uniacid(self, db: Session, *, uniacid: int) -> Optional[UniAccountModulesShortcut]:
return self.get_by_field(db, "uniacid", uniacid)
class CRUDUniAccountUsers(CRUDBase[UniAccountUsers, UniAccountUsersCreate, UniAccountUsersUpdate]):
def get_by_uniacid(self, db: Session, *, uniacid: int) -> Optional[UniAccountUsers]:
return self.get_by_field(db, "uniacid", uniacid)
def get_by_uid(self, db: Session, *, uid: int) -> Optional[UniAccountUsers]:
return self.get_by_field(db, "uid", uid)
class CRUDUniGroup(CRUDBase[UniGroup, UniGroupCreate, UniGroupUpdate]):
def get_by_uniacid(self, db: Session, *, uniacid: int) -> Optional[UniGroup]:
return self.get_by_field(db, "uniacid", uniacid)
def get_by_owner(self, db: Session, *, owner_uid: int) -> Optional[UniGroup]:
return self.get_by_field(db, "owner_uid", owner_uid)
class CRUDUniLinkUniacid(CRUDBase[UniLinkUniacid, UniLinkUniacidCreate, UniLinkUniacidUpdate]):
def get_by_uniacid(self, db: Session, *, uniacid: int) -> Optional[UniLinkUniacid]:
return self.get_by_field(db, "uniacid", uniacid)
class CRUDUniModules(CRUDBase[UniModules, UniModulesCreate, UniModulesUpdate]):
def get_by_uniacid(self, db: Session, *, uniacid: int) -> Optional[UniModules]:
return self.get_by_field(db, "uniacid", uniacid)
class CRUDUniVerifycode(CRUDBase[UniVerifycode, UniVerifycodeCreate, UniVerifycodeUpdate]):
def get_by_uniacid(self, db: Session, *, uniacid: int) -> Optional[UniVerifycode]:
return self.get_by_field(db, "uniacid", uniacid)
def get_by_receiver(self, db: Session, *, receiver: str) -> Optional[UniVerifycode]:
return self.get_by_field(db, "receiver", receiver)
class CRUDUniSettings(CRUDBase[UniSettings, UniSettingsCreate, UniSettingsUpdate]):
def get_by_uniacid(self, db: Session, *, uniacid: int) -> Optional[UniSettings]:
return db.query(self.model).filter(self.model.uniacid == uniacid).first()
def create_with_uniacid(
self, db: Session, *, obj_in: UniSettingsCreate
) -> UniSettings:
"""创建设置时使用uniacid作为主键"""
db_obj = UniSettings(**obj_in.dict())
db.add(db_obj)
db.commit()
db.refresh(db_obj)
return db_obj
# 创建实例
uni_account = CRUDUniAccount(UniAccount)
uni_account_extra_modules = CRUDUniAccountExtraModules(UniAccountExtraModules)
uni_account_group = CRUDUniAccountGroup(UniAccountGroup)
uni_account_menus = CRUDUniAccountMenus(UniAccountMenus)
uni_account_modules = CRUDUniAccountModules(UniAccountModules)
uni_account_modules_shortcut = CRUDUniAccountModulesShortcut(UniAccountModulesShortcut)
uni_account_users = CRUDUniAccountUsers(UniAccountUsers)
uni_group = CRUDUniGroup(UniGroup)
uni_link_uniacid = CRUDUniLinkUniacid(UniLinkUniacid)
uni_modules = CRUDUniModules(UniModules)
uni_verifycode = CRUDUniVerifycode(UniVerifycode)
uni_settings = CRUDUniSettings(UniSettings)

View File

@ -9,5 +9,6 @@ from mooc.models.account import (
AccountWebapp,
AccountWxapp,
AccountXzapp,
Account,
)
Account
)
from mooc.models.uni_account import UniAccount, UniAccountExtraModules, UniAccountGroup, UniAccountMenus, UniAccountModules

View File

@ -1,8 +1,16 @@
from sqlalchemy import create_engine
from sqlalchemy import create_engine, inspect
from sqlalchemy.ext.declarative import declarative_base
from sqlalchemy.orm import sessionmaker
from mooc.core.config import settings
from typing import Generator
from typing import Generator, Set
import importlib
import pkgutil
from pathlib import Path
import logging
# 配置日志
logger = logging.getLogger(__name__)
# 创建数据库引擎
engine = create_engine(
settings.SQLALCHEMY_DATABASE_URI,
@ -16,9 +24,61 @@ SessionLocal = sessionmaker(autocommit=False, autoflush=False, bind=engine)
# 创建基类
Base = declarative_base()
def init_db():
"""初始化数据库"""
Base.metadata.create_all(bind=engine)
def get_existing_tables() -> Set[str]:
"""获取数据库中已存在的表"""
inspector = inspect(engine)
return set(inspector.get_table_names())
def import_models() -> None:
"""
自动导入所有模型
这确保所有模型类都被正确地注册到Base.metadata
"""
models_path = Path(__file__).parent.parent / "models"
for module_info in pkgutil.iter_modules([str(models_path)]):
importlib.import_module(f"mooc.models.{module_info.name}")
# 导入后立即验证
from mooc.models import verify_all_models
verify_all_models()
def create_missing_tables() -> None:
"""创建缺失的表"""
existing_tables = get_existing_tables()
metadata_tables = set(Base.metadata.tables.keys())
missing_tables = metadata_tables - existing_tables
if missing_tables:
logger.info(f"Creating missing tables: {missing_tables}")
# 只创建缺失的表
for table_name in missing_tables:
if table_name in Base.metadata.tables:
Base.metadata.tables[table_name].create(engine)
else:
logger.info("All tables already exist")
def init_db() -> None:
"""
初始化数据库
1. 导入所有模型并验证
2. 检查并创建缺失的表
"""
try:
# 确保所有模型都被导入并验证
import_models()
logger.info("All models imported successfully")
# 创建缺失的表
create_missing_tables()
logger.info("Database initialization completed successfully")
# 打印所有已注册的表名(用于调试)
from mooc.models import get_all_table_names
logger.debug(f"Registered tables: {get_all_table_names()}")
except Exception as e:
logger.error(f"Database initialization failed: {str(e)}")
raise
def get_db() -> Generator:
"""

View File

@ -0,0 +1,82 @@
# 显式导入所有模型模块
from mooc.models.admin import * # noqa
from mooc.models.account import * # noqa
from mooc.models.uni_account import * # noqa
# 导出常用的模型类
from mooc.models.account import (
Account,
AccountWechats,
AccountAliapp,
AccountBaiduapp,
AccountPhoneapp,
AccountToutiaoapp,
AccountWebapp,
AccountWxapp,
AccountXzapp
)
from mooc.models.uni_account import (
UniAccount,
UniAccountExtraModules,
UniAccountGroup,
UniAccountMenus,
UniAccountModules,
UniAccountModulesShortcut,
UniAccountUsers,
UniGroup,
UniLinkUniacid,
UniModules,
UniSettings,
UniVerifycode
)
def verify_all_models():
"""验证所有模型是否已正确注册到Base.metadata"""
from mooc.db.database import Base
# 所有预期的表名
expected_tables = {
'ims_goouc_fullexam_admin',
# Account 相关表
'ims_account',
'ims_account_aliapp',
'ims_account_baiduapp',
'ims_account_phoneapp',
'ims_account_toutiaoapp',
'ims_account_webapp',
'ims_account_wechats',
'ims_account_wxapp',
'ims_account_xzapp',
# UniAccount 相关表
'ims_uni_account',
'ims_uni_account_extra_modules',
'ims_uni_account_group',
'ims_uni_account_menus',
'ims_uni_account_modules',
'ims_uni_account_modules_shortcut',
'ims_uni_account_users',
'ims_uni_group',
'ims_uni_link_uniacid',
'ims_uni_modules',
'ims_uni_settings',
'ims_uni_verifycode'
}
actual_tables = set(Base.metadata.tables.keys())
missing_tables = expected_tables - actual_tables
extra_tables = actual_tables - expected_tables
if missing_tables:
raise RuntimeError(f"Missing tables in metadata: {missing_tables}")
if extra_tables:
print(f"Warning: Found unexpected tables: {extra_tables}")
return True
def get_all_table_names():
"""获取所有已注册的表名"""
from mooc.db.database import Base
return sorted(Base.metadata.tables.keys())

187
mooc/models/uni_account.py Normal file
View File

@ -0,0 +1,187 @@
from sqlalchemy import Column, Integer, String, Text, SmallInteger
from mooc.db.database import Base
class UniAccount(Base):
__tablename__ = "ims_uni_account"
uniacid = Column(Integer, primary_key=True, autoincrement=True)
groupid = Column(Integer, nullable=False)
name = Column(String(100), nullable=False)
description = Column(String(255), nullable=False)
default_acid = Column(Integer, nullable=False)
rank = Column(Integer)
title_initial = Column(String(1), nullable=False)
createtime = Column(Integer, nullable=False)
logo = Column(String(255), nullable=False)
qrcode = Column(String(255), nullable=False)
create_uid = Column(Integer, nullable=False)
class Config:
from_attributes = True
class UniAccountExtraModules(Base):
__tablename__ = "ims_uni_account_extra_modules"
id = Column(Integer, primary_key=True, autoincrement=True)
uniacid = Column(Integer, index=True, nullable=False)
modules = Column(Text, nullable=False)
class Config:
from_attributes = True
class UniAccountGroup(Base):
__tablename__ = "ims_uni_account_group"
id = Column(Integer, primary_key=True, autoincrement=True)
uniacid = Column(Integer, nullable=False)
groupid = Column(Integer, nullable=False)
class Config:
from_attributes = True
class UniAccountMenus(Base):
__tablename__ = "ims_uni_account_menus"
id = Column(Integer, primary_key=True, autoincrement=True)
uniacid = Column(Integer, index=True, nullable=False)
menuid = Column(Integer, index=True, nullable=False)
type = Column(SmallInteger, nullable=False)
title = Column(String(30), nullable=False)
sex = Column(SmallInteger, nullable=False)
group_id = Column(Integer, nullable=False)
client_platform_type = Column(SmallInteger, nullable=False)
area = Column(String(50), nullable=False)
data = Column(Text, nullable=False)
status = Column(SmallInteger, nullable=False)
createtime = Column(Integer, nullable=False)
isdeleted = Column(SmallInteger, nullable=False)
class Config:
from_attributes = True
class UniAccountModules(Base):
__tablename__ = "ims_uni_account_modules"
id = Column(Integer, primary_key=True, autoincrement=True)
uniacid = Column(Integer, index=True, nullable=False)
module = Column(String(50), index=True, nullable=False)
enabled = Column(SmallInteger, nullable=False)
settings = Column(Text, nullable=False)
shortcut = Column(SmallInteger, nullable=False)
displayorder = Column(Integer, nullable=False)
class Config:
from_attributes = True
class UniAccountModulesShortcut(Base):
__tablename__ = "ims_uni_account_modules_shortcut"
id = Column(Integer, primary_key=True, autoincrement=True)
title = Column(String(200), nullable=False)
url = Column(String(250), nullable=False)
icon = Column(String(200), nullable=False)
uniacid = Column(Integer, nullable=False)
version_id = Column(Integer, nullable=False)
module_name = Column(String(200), nullable=False)
class Config:
from_attributes = True
class UniAccountUsers(Base):
__tablename__ = "ims_uni_account_users"
id = Column(Integer, primary_key=True, autoincrement=True)
uniacid = Column(Integer, index=True, nullable=False)
uid = Column(Integer, index=True, nullable=False)
role = Column(String(255), nullable=False)
rank = Column(SmallInteger, nullable=False)
class Config:
from_attributes = True
class UniGroup(Base):
__tablename__ = "ims_uni_group"
id = Column(Integer, primary_key=True, autoincrement=True)
owner_uid = Column(Integer, nullable=False)
name = Column(String(50), nullable=False)
modules = Column(Text, nullable=False)
templates = Column(String(5000), nullable=False)
uniacid = Column(Integer, index=True, nullable=False)
uid = Column(Integer, nullable=False)
class Config:
from_attributes = True
class UniLinkUniacid(Base):
__tablename__ = "ims_uni_link_uniacid"
id = Column(Integer, primary_key=True, autoincrement=True)
uniacid = Column(Integer, nullable=False)
link_uniacid = Column(Integer, nullable=False)
version_id = Column(Integer, nullable=False)
module_name = Column(String(255), nullable=False)
class Config:
from_attributes = True
class UniModules(Base):
__tablename__ = "ims_uni_modules"
id = Column(Integer, primary_key=True, autoincrement=True)
uniacid = Column(Integer, index=True, nullable=False)
module_name = Column(String(50), nullable=False)
class Config:
from_attributes = True
class UniVerifycode(Base):
__tablename__ = "ims_uni_verifycode"
id = Column(Integer, primary_key=True, autoincrement=True)
uniacid = Column(Integer, nullable=False)
receiver = Column(String(50), nullable=False)
verifycode = Column(String(6), nullable=False)
total = Column(SmallInteger, nullable=False)
createtime = Column(Integer, nullable=False)
failed_count = Column(Integer)
class Config:
from_attributes = True
class UniSettings(Base):
__tablename__ = "ims_uni_settings"
uniacid = Column(Integer, primary_key=True)
passport = Column(String(200), nullable=False)
oauth = Column(String(100), nullable=False)
jsauth_acid = Column(Integer, nullable=False)
notify = Column(String(2000), nullable=False)
creditnames = Column(String(500), nullable=False)
creditbehaviors = Column(String(500), nullable=False)
welcome = Column(String(60), nullable=False)
default = Column(String(60), nullable=False)
default_message = Column(String(2000), nullable=False)
payment = Column(Text, nullable=False)
stat = Column(String(300), nullable=False)
default_site = Column(Integer)
sync = Column(SmallInteger, nullable=False)
recharge = Column(String(500), nullable=False)
tplnotice = Column(String(2000), nullable=False)
grouplevel = Column(SmallInteger, nullable=False)
mcplugin = Column(String(500), nullable=False)
exchange_enable = Column(SmallInteger, nullable=False)
coupon_type = Column(SmallInteger, nullable=False)
menuset = Column(Text, nullable=False)
statistics = Column(String(100), nullable=False)
bind_domain = Column(String(200), nullable=False)
comment_status = Column(SmallInteger, nullable=False)
reply_setting = Column(SmallInteger, nullable=False)
default_module = Column(String(100), nullable=False)
attachment_limit = Column(Integer, nullable=False)
attachment_size = Column(String(20), nullable=False)
sync_member = Column(SmallInteger, nullable=False)
remote = Column(String(2000), nullable=False)
class Config:
from_attributes = True

319
mooc/schemas/uni_account.py Normal file
View File

@ -0,0 +1,319 @@
from pydantic import BaseModel
from typing import Optional
class UniAccountBase(BaseModel):
groupid: int
name: str
description: str
default_acid: int
rank: Optional[int]
title_initial: str
createtime: int
logo: str
qrcode: str
create_uid: int
class UniAccountCreate(UniAccountBase):
pass
class UniAccountUpdate(BaseModel):
groupid: Optional[int]
name: Optional[str]
description: Optional[str]
default_acid: Optional[int]
rank: Optional[int]
title_initial: Optional[str]
logo: Optional[str]
qrcode: Optional[str]
create_uid: Optional[int]
class UniAccountRead(UniAccountBase):
uniacid: int
class Config:
from_attributes = True
class UniAccountExtraModulesBase(BaseModel):
uniacid: int
modules: str
class UniAccountExtraModulesCreate(UniAccountExtraModulesBase):
pass
class UniAccountExtraModulesUpdate(BaseModel):
modules: Optional[str]
class UniAccountExtraModulesRead(UniAccountExtraModulesBase):
id: int
class Config:
from_attributes = True
class UniAccountGroupBase(BaseModel):
uniacid: int
groupid: int
class UniAccountGroupCreate(UniAccountGroupBase):
pass
class UniAccountGroupUpdate(BaseModel):
groupid: Optional[int]
class UniAccountGroupRead(UniAccountGroupBase):
id: int
class Config:
from_attributes = True
class UniAccountMenusBase(BaseModel):
uniacid: int
menuid: int
type: int
title: str
sex: int
group_id: int
client_platform_type: int
area: str
data: str
status: int
createtime: int
isdeleted: int
class UniAccountMenusCreate(UniAccountMenusBase):
pass
class UniAccountMenusUpdate(BaseModel):
type: Optional[int]
title: Optional[str]
sex: Optional[int]
group_id: Optional[int]
client_platform_type: Optional[int]
area: Optional[str]
data: Optional[str]
status: Optional[int]
isdeleted: Optional[int]
class UniAccountMenusRead(UniAccountMenusBase):
id: int
class Config:
from_attributes = True
class UniAccountModulesBase(BaseModel):
uniacid: int
module: str
enabled: int
settings: str
shortcut: int
displayorder: int
class UniAccountModulesCreate(UniAccountModulesBase):
pass
class UniAccountModulesUpdate(BaseModel):
module: Optional[str]
enabled: Optional[int]
settings: Optional[str]
shortcut: Optional[int]
displayorder: Optional[int]
class UniAccountModulesRead(UniAccountModulesBase):
id: int
class Config:
from_attributes = True
class UniAccountModulesShortcutBase(BaseModel):
title: str
url: str
icon: str
uniacid: int
version_id: int
module_name: str
class UniAccountModulesShortcutCreate(UniAccountModulesShortcutBase):
pass
class UniAccountModulesShortcutUpdate(BaseModel):
title: Optional[str]
url: Optional[str]
icon: Optional[str]
version_id: Optional[int]
module_name: Optional[str]
class UniAccountModulesShortcutRead(UniAccountModulesShortcutBase):
id: int
class Config:
from_attributes = True
class UniAccountUsersBase(BaseModel):
uniacid: int
uid: int
role: str
rank: int
class UniAccountUsersCreate(UniAccountUsersBase):
pass
class UniAccountUsersUpdate(BaseModel):
role: Optional[str]
rank: Optional[int]
class UniAccountUsersRead(UniAccountUsersBase):
id: int
class Config:
from_attributes = True
class UniGroupBase(BaseModel):
owner_uid: int
name: str
modules: str
templates: str
uniacid: int
uid: int
class UniGroupCreate(UniGroupBase):
pass
class UniGroupUpdate(BaseModel):
name: Optional[str]
modules: Optional[str]
templates: Optional[str]
owner_uid: Optional[int]
uid: Optional[int]
class UniGroupRead(UniGroupBase):
id: int
class Config:
from_attributes = True
class UniLinkUniacidBase(BaseModel):
uniacid: int
link_uniacid: int
version_id: int
module_name: str
class UniLinkUniacidCreate(UniLinkUniacidBase):
pass
class UniLinkUniacidUpdate(BaseModel):
link_uniacid: Optional[int]
version_id: Optional[int]
module_name: Optional[str]
class UniLinkUniacidRead(UniLinkUniacidBase):
id: int
class Config:
from_attributes = True
class UniModulesBase(BaseModel):
uniacid: int
module_name: str
class UniModulesCreate(UniModulesBase):
pass
class UniModulesUpdate(BaseModel):
module_name: Optional[str]
class UniModulesRead(UniModulesBase):
id: int
class Config:
from_attributes = True
class UniVerifycodeBase(BaseModel):
uniacid: int
receiver: str
verifycode: str
total: int
createtime: int
failed_count: Optional[int]
class UniVerifycodeCreate(UniVerifycodeBase):
pass
class UniVerifycodeUpdate(BaseModel):
verifycode: Optional[str]
total: Optional[int]
failed_count: Optional[int]
class UniVerifycodeRead(UniVerifycodeBase):
id: int
class Config:
from_attributes = True
class UniSettingsBase(BaseModel):
uniacid: int
passport: str
oauth: str
jsauth_acid: int
notify: str
creditnames: str
creditbehaviors: str
welcome: str
default: str
default_message: str
payment: str
stat: str
default_site: Optional[int]
sync: int
recharge: str
tplnotice: str
grouplevel: int
mcplugin: str
exchange_enable: int
coupon_type: int
menuset: str
statistics: str
bind_domain: str
comment_status: int
reply_setting: int
default_module: str
attachment_limit: int
attachment_size: str
sync_member: int
remote: str
class UniSettingsCreate(UniSettingsBase):
pass
class UniSettingsUpdate(BaseModel):
passport: Optional[str]
oauth: Optional[str]
jsauth_acid: Optional[int]
notify: Optional[str]
creditnames: Optional[str]
creditbehaviors: Optional[str]
welcome: Optional[str]
default: Optional[str]
default_message: Optional[str]
payment: Optional[str]
stat: Optional[str]
default_site: Optional[int]
sync: Optional[int]
recharge: Optional[str]
tplnotice: Optional[str]
grouplevel: Optional[int]
mcplugin: Optional[str]
exchange_enable: Optional[int]
coupon_type: Optional[int]
menuset: Optional[str]
statistics: Optional[str]
bind_domain: Optional[str]
comment_status: Optional[int]
reply_setting: Optional[int]
default_module: Optional[str]
attachment_limit: Optional[int]
attachment_size: Optional[str]
sync_member: Optional[int]
remote: Optional[str]
class UniSettingsRead(UniSettingsBase):
class Config:
from_attributes = True