重构第一版:重新验证2.0推荐写法

This commit is contained in:
geeker
2026-09-24 17:19:56 +08:00
parent 81db17ba9e
commit 0d71808498
21 changed files with 1887 additions and 936 deletions
+9
View File
@@ -0,0 +1,9 @@
# python tech research
> 现状与趋势
## server
## orm
+48
View File
@@ -0,0 +1,48 @@
from typing import Optional
from sqlalchemy import Column, Integer, create_engine, String, DateTime,func
from sqlalchemy.ext.asyncio import create_async_engine, async_sessionmaker, AsyncSession
from sqlalchemy.orm import sessionmaker, declarative_base, DeclarativeBase, Mapped,mapped_column
from fastapi import APIRouter, Depends
from debug.orm_app.sqlalchemy_full_app import User
from datetime import datetime
db_url = "mysql+pymysql://geeker:geeker@localhost:3306/fastapi_tutor?charset=utf8mb4"
engine = create_engine(db_url)
session = sessionmaker(engine, expire_on_commit=False)
# Base 基类
class Base(DeclarativeBase):
pass
class MetaBase(Base):
__tablename__ = "base_mapped_column"
# id = Column(Integer, primary_key=True)
id:Mapped[int] = mapped_column(primary_key=True,autoincrement=True,nullable=False)
# mapped_column: 默认 nullable=False
num:Mapped[str] = mapped_column(String(30),unique=True) # 唯一键
name:Mapped[str] = mapped_column(String(30),default="") #
name1:Mapped[str] = mapped_column(String(30),nullable=True)
# name2:Optional[str] = mapped_column(String(30)) # 报错
name3:Mapped[str | None] = mapped_column(String(30),nullable=True)
name4:Mapped[Optional[str]] = mapped_column(String(30),nullable=True)
age:Mapped[int] = mapped_column(Integer,default=18)
# 默认null
education:Mapped[str] = mapped_column(String(50),nullable=True)
create_time:Mapped[datetime] = mapped_column(server_default=func.now())
update_time:Mapped[datetime] = mapped_column(server_default=func.now(),onupdate=func.now())
pass
Base.metadata.create_all(engine)
+58
View File
@@ -0,0 +1,58 @@
from sqlalchemy import Column, Integer, create_engine, String, ForeignKey,DATETIME,DateTime,func
from sqlalchemy.ext.asyncio import create_async_engine, async_sessionmaker, AsyncSession
from sqlalchemy.orm import sessionmaker,declarative_base,DeclarativeBase
from fastapi import APIRouter, Depends
from debug.orm_app.sqlalchemy_full_app import User
from datetime import datetime
db_url = "mysql+pymysql://geeker:geeker@localhost:3306/fastapi_tutor?charset=utf8mb4"
engine = create_engine(db_url)
session = sessionmaker(engine, expire_on_commit=False)
# 外键引用
Base = declarative_base()
class MetaBaseFunc(Base):
__tablename__ = "meta_base_func"
id = Column(Integer, primary_key=True)
pass
# Base.metadata.create_all(engine)
# Base 基类 - 可行,但不建议用多个Base分别创建表
# class Base(DeclarativeBase):
# pass
class MetaBase(Base):
__tablename__ = "base_column_test"
id = Column(Integer, primary_key=True)
num = Column(String(30),nullable=False,unique=True)
name = Column(String(30),nullable=False,default="")
# null
education = Column(String(50), nullable=True)
# 索引与外键 - 运行时查找
f_id = Column(Integer,ForeignKey("meta_base_func.id"),nullable=False, index=True)
fd_id = Column(Integer,ForeignKey("meta_base_func.id"),nullable=True)
# 日期处理
create_date = Column(DATETIME
, default=datetime.now # 默认值是当前时间
)
create_date1 = Column(DateTime, default=datetime.utcnow())
update_date = Column(DATETIME
, default=datetime.now # 首次创建的时间跟更新时间一致
, onupdate=datetime.now
)
# 默认值处理
create_time = Column(DateTime, nullable=False, server_default=func.now())
update_time = Column(DateTime, nullable=False, server_default=func.now(), onupdate=func.now())
Base.metadata.create_all(engine)
+47
View File
@@ -0,0 +1,47 @@
from sqlalchemy import ForeignKey,String,create_engine
from sqlalchemy.orm import DeclarativeBase, Mapped, mapped_column, relationship,declarative_base
db_url = "mysql+pymysql://geeker:geeker@localhost:3306/fastapi_tutor?charset=utf8mb4"
engine = create_engine(db_url, pool_size= 50, echo=True)
class Base(DeclarativeBase):
pass
class Teacher(Base):
__tablename__ = "mapped_teachers"
id: Mapped[int] = mapped_column(primary_key=True)
tname: Mapped[str] = mapped_column(String(30))
# 反向关系:这个老师当班主任的所有班级
head_teacher_of: Mapped[list["Class"]] = relationship(
"Class",
foreign_keys="Class.head_teacher_id",
back_populates="head_teacher"
)
coach_teacher_of: Mapped[list["Class"]] = relationship(
"Class",
foreign_keys="Class.coach_teacher_id",
back_populates="coach_teacher"
)
class Class(Base):
__tablename__ = "mapped_classes"
id: Mapped[int] = mapped_column(primary_key=True)
class_num: Mapped[str] = mapped_column(String(30))
head_teacher_id: Mapped[int] = mapped_column(ForeignKey("mapped_teachers.id"))
coach_teacher_id: Mapped[int] = mapped_column(ForeignKey("mapped_teachers.id"))
head_teacher: Mapped["Teacher"] = relationship(
"Teacher",
foreign_keys=[head_teacher_id],
back_populates="head_teacher_of"
)
coach_teacher: Mapped["Teacher"] = relationship(
"Teacher",
foreign_keys=[coach_teacher_id],
back_populates="coach_teacher_of"
)
Base.metadata.create_all(engine)
+3
View File
@@ -1,3 +1,6 @@
'''
pymysql 更底层封装sql - 游标
'''
import pymysql.cursors
# Connect to the database
+28
View File
@@ -0,0 +1,28 @@
from sqlalchemy import Column, Integer,create_engine
from sqlalchemy.ext.asyncio import create_async_engine, async_sessionmaker, AsyncSession
from sqlalchemy.orm import sessionmaker,declarative_base,DeclarativeBase
from fastapi import APIRouter, Depends
from debug.orm_app.sqlalchemy_full_app import User
db_url = "mysql+pymysql://geeker:geeker@localhost:3306/fastapi_tutor?charset=utf8mb4"
engine = create_engine(db_url)
# 测试autoflush - True
session = sessionmaker(engine, autoflush=True ,expire_on_commit=False)
# Base 基类
class Base(DeclarativeBase):
pass
class MetaBase(Base):
__tablename__ = "base_autoflush"
id = Column(Integer, primary_key=True)
pass
Base.metadata.create_all(engine)
-234
View File
@@ -1,234 +0,0 @@
from sqlalchemy import create_engine, Column, Integer,String,DATETIME,DECIMAL, or_, and_,not_,func
from sqlalchemy.orm import declarative_base, sessionmaker
from datetime import datetime
db_url = "mysql+pymysql://geeker:geeker@localhost:3306/fastapi_tutor?charset=utf8mb4"
engine = create_engine(db_url, pool_size= 50, echo=True)
Base = declarative_base() # 获取基类!
class Order(Base): # python里的表名字
__tablename__ = 'order_info_detail' # 实际数据库的表名字
id = Column( Integer # 声明字段的数据类型
, primary_key=True # 声明是主键
, autoincrement=True # 声明是自增主键
, comment='订单编号,自增主键' # 注释
)
title = Column( String(50) # 对应数据库的varchar类型
,nullable=False # 不允许为null
)
price = Column(DECIMAL)
userid = Column( Integer
# ,ForeignKey('user_info_detail.id')
,nullable=False ) # 外键约束
create_date = Column(DATETIME
, default=datetime.now # 默认值是当前时间
)
update_date = Column(DATETIME
, default=datetime.now # 首次创建的时间跟更新时间一致
, onupdate=datetime.now
)
class User(Base): # python里的表名字
__tablename__ = 'user_info_detail' # 实际数据库的表名字
id = Column( Integer # 声明字段的数据类型
, primary_key=True # 声明是主键
, autoincrement=True # 声明是自增主键
, comment='用户编号,自增主键' # 注释
)
username = Column( String(50) # 对应数据库的varchar类型
,nullable=False # 不允许为null
,comment='用户名'
)
create_date = Column(DATETIME
, default=datetime.now # 默认值是当前时间
)
update_date = Column(DATETIME
, default=datetime.now # 首次创建的时间跟更新时间一致
, onupdate=datetime.now
)
Base.metadata.create_all(engine) # 所有表创建 <- 只要数据库存在这个表了,就不会触发,也不会更新表结构
# Order.__table__.create(engine,checkfirst = True) # 单张表的创建
# 三、【表数据的新增】
'''1.实例化数据库表模型类,得到具体的数据'''
u1 = User( username='清风飞扬' )
print( 'User1的属性:',u1.id,u1.username,u1.create_date,u1.update_date )
u2 = User( username='北大青鸟' )
print( 'User2的属性:',u2.username)
'''2.将实例化好的数据,添加到数据库里'''
# 拿到数据库会话管理工具
Session = sessionmaker( bind=engine
,autoflush=False # 是否开启自动刷新python新增的数据到实际的数据库内存缓存中
,autocommit = False # 不自动提交数据,这个是真正提交到数据库磁盘永久生效的
)
session = Session() # 实例化一个数据库操作会话
# session.add( u1 ) # 新增数据到数据库里
# session.add( u2 )
session.commit() # 提交,永久生效,注意提交后不能回滚
print(session.query(User).all())
#
# # session.rollback() # 回滚,事务没有提交前,dml操作可以回滚
# session.close() # 关闭数据操作会话
#
#
# '''
# 等价于sql语句:
# insert into user_info_detail(username) values('清风飞扬');
# insert into user_info_detail(username) values('北大青鸟');
# '''
#
# # 四、【表数据的更改】
# session = Session() # 实例化一个数据库操作会话
# print(f'{session.query(User)=}, {session.query(User).all()=}')
# session.query(User)\
# .filter( User.username == '北大青鸟' )\
# .update( {"username":'沃林数智'
# , "create_date":"2000-10-10"
# } # 同时更新多个字段
# )
# session.commit()
# '''
# 多个复合条件:
# filter( 条件1,条件2,条件3.. ) # and的关系
#
# filter( or_( 条件1,条件2), not_(条件2),and_(条件1,条件2) )
#
# session.query(表模型).filter(条件1).filter(条件2).filter(条件3) 条件可以拼接成and的关系
#
# or_: 函数里的条件都是 or 的关系
# and_: 函数里的条件是 and 的关系
# not_ : 将条件的结果进行取反
# '''
#
# # 五、【表数据的删除】
# try:
# session.query( User ).filter( User.username == '清风飞扬' ).delete() # 只要命中就删除
# session.commit()
# except:
# session.rollback() # 如果报错,就回滚
#
# # 清空数据,并且重置自增主键 truncate table 表名; 无法回滚
# # session.execute( text( "truncate table user_info_detail" ) ) # 直接书写原生的sql语句
# # 可以select、update、delete全部支持
'''1.单表基础查询'''
# ① 单条数据查询 first(),返回的是一个查询结果对象
r1 = session.query(User).first()
print('获取单个查询结果对象:',r1)
print(r1.id,r1.usernmae,r1.create_date,r1.update_date)
# ② 全量查询 all() , 返回的是一个列表list
r2 = session.query(User).all()
print('获取多个查询结果对象:',r2)
for i in range( len(r2) ):
print(f'第{i+1}行数据:',r2[i].id,r2[i].usernmae,r2[i].create_date,r2[i].update_date)
q = session.query(User) # 得到一个查询语句对象
r3 = q.all() # 获取查询语句对象的所有内容
print(q)
print(r3)
# ③ where 条件查询
r4 = session.query(User).filter( or_(User.id == 1, User.usernmae == '李四') ).all()
for i in r4:
print(i.id,i.usernmae)
# ④ like模糊匹配查询
r5 = session.query(User).where( User.usernmae.like('%三%') ).all()
for i in r5:
print('like模糊匹配:',i.id, i.usernmae)
# ⑤ order by排序
r5 = session.query(User).order_by(User.id.desc(), User.usernmae).all()
for i in r5:
print('排序:', i.id, i.usernmae)
# ⑥ limit 分页
'''
分页公式:
原生sql:limit( (页数-1)*每页数据量, 每页数据量 )
orm里: offset( (页数-1)*每页数据量 ).limit(每页数据量)
'''
n = 1 # 页数
m = 2 # 每页数据量
r6 = session.query(User).offset((n-1)*m).limit(m).all()
for i in r6:
print('分页:', i.id, i.usernmae)
'''2.分组聚合group by'''
'''
select usernmae,count(1)
from user_info_detail
group by usernmae
having count(1) >= 2
'''
r7 = session.query(User.usernmae,func.count(User.id).label('num')).\
group_by( User.usernmae ).\
having( func.count(User.id) >= 2 ).\
all()
for i in r7:
print('分组聚合:',i.usernmae,i.num)
'''
func函数支持:max、min、sum、count、avg常用的聚合函数
用法: func.count(聚合的字段)
'''
'''3.多表关联查询join内连接/outerjoin左连接'''
r8 = session.query(User.id.label('user_id') , User.usernmae, Order.id.label('order_id'), Order.title ).\
join( Order, User.id == Order.userid ).\
order_by(User.id).\
all()
for i in r8:
print('多表关联内连接:',i.user_id,i.usernmae,i.order_id,i.title)
# outerjoin(谁放在里面,谁就是从表)
r8 = session.query(User.id.label('user_id') , User.usernmae, Order.id.label('order_id'), Order.title ).\
outerjoin( Order, User.id == Order.userid ).\
order_by(User.id).\
all()
for i in r8:
print('多表关联左连接:',i.user_id,i.usernmae,i.order_id,i.title)
'''
select ——> session.query( 表模型名 )
from 表1
join 表2 on 条件 ——> join(连接的表,条件) / outerjoin(连接的表,条件)
where 筛选条件 ——> filter(条件)
group by 分组字段 ——> group_by(分组的字段)
having 分组后过滤 ——> having(过滤的条件)
order by 排序 ——> order_by( 排序的字段.desc() )
limit 分页 ——> offset(偏移量).limit(数据量)
'''
n = 1 # 页数
m = 2 # 每页数据量
r9 = session.query(User.usernmae,Order.title,func.count(1).label('ordernum')).\
join(Order,User.id == Order.userid).\
filter(Order.title == '苹果').\
group_by(User.usernmae,Order.title).\
having(func.count(1) >= 1).\
order_by(func.count(1).desc()).\
offset((n-1)*m).limit(m).\
all()
for i in r9:
print('完整的查询:',i.usernmae,i.title,i.ordernum)
+246
View File
@@ -0,0 +1,246 @@
from sqlalchemy import create_engine, Column, Integer,String,DATETIME,DECIMAL, or_, and_,not_,func, Boolean
from sqlalchemy.orm import declarative_base, sessionmaker
from datetime import datetime
from model.template import Template
db_url = "mysql+pymysql://geeker:geeker@localhost:3306/fastapi_tutor?charset=utf8mb4"
engine = create_engine(db_url, pool_size= 50, echo=True)
Base = declarative_base() # 获取基类!
class Order(Base): # python里的表名字
__tablename__ = 'order' # 实际数据库的表名字
id = Column( Integer # 声明字段的数据类型
, primary_key=True # 声明是主键
, autoincrement=True # 声明是自增主键
, comment='订单编号,自增主键' # 注释
)
title = Column( String(50) # 对应数据库的varchar类型
,nullable=False # 不允许为null
)
price = Column(DECIMAL)
userid = Column( Integer
# ,ForeignKey('user_info_detail.id')
,nullable=False ) # 外键约束
create_date = Column(DATETIME
, default=datetime.now # 默认值是当前时间
)
update_date = Column(DATETIME
, default=datetime.now # 首次创建的时间跟更新时间一致
, onupdate=datetime.now
)
class User(Base,Template): # python里的表名字
__tablename__ = 'user_template' # 实际数据库的表名字
username = Column( String(50) # 对应数据库的varchar类型
,nullable=False # 不允许为null
,comment='用户名'
)
# class User(Base): # python里的表名字
# __tablename__ = 'user' # 实际数据库的表名字
# id = Column( Integer # 声明字段的数据类型
# , primary_key=True # 声明是主键
# , autoincrement=True # 声明是自增主键
# , comment='用户编号,自增主键' # 注释
# )
# username = Column( String(50) # 对应数据库的varchar类型
# ,nullable=False # 不允许为null
# ,comment='用户名'
# )
# create_datetime = Column(DATETIME
# , default=datetime.now # 默认值是当前时间
# )
# update_datetime = Column(DATETIME
# , default=datetime.now # 首次创建的时间跟更新时间一致
# , onupdate=datetime.now
# )
# is_deleted = Column(Boolean, default=False )
# delete_datetime = Column(DATETIME, nullable=True)
Base.metadata.create_all(engine) # 所有表创建 <- 只要数据库存在这个表了,就不会触发,也不会更新表结构
# Order.__table__.create(engine,checkfirst = True) # 单张表的创建
# 三、【表数据的新增】
'''1.实例化数据库表模型类,得到具体的数据'''
u1 = User( username='清风飞扬' )
print( 'User1的属性:',u1.id,u1.username,u1.create_datetime,u1.update_datetime )
u2 = User( username='北大青鸟' )
print( 'User2的属性:',u2.username)
'''2.将实例化好的数据,添加到数据库里'''
# 拿到数据库会话管理工具
Session = sessionmaker( bind=engine
,autoflush=False # 是否开启自动刷新python新增的数据到实际的数据库内存缓存中
,autocommit = False # 不自动提交数据,这个是真正提交到数据库磁盘永久生效的
)
session = Session() # 实例化一个数据库操作会话
session.add( u1 ) # 新增数据到数据库里
session.add( u2 )
session.commit() # 提交,永久生效,注意提交后不能回滚
print(session.query(User).all())
#
# # session.rollback() # 回滚,事务没有提交前,dml操作可以回滚
# session.close() # 关闭数据操作会话
#
#
# '''
# 等价于sql语句:
# insert into user_info_detail(username) values('清风飞扬');
# insert into user_info_detail(username) values('北大青鸟');
# '''
#
# # 四、【表数据的更改】
# session = Session() # 实例化一个数据库操作会话
# print(f'{session.query(User)=}, {session.query(User).all()=}')
# session.query(User)\
# .filter( User.username == '北大青鸟' )\
# .update( {"username":'沃林数智'
# , "create_date":"2000-10-10"
# } # 同时更新多个字段
# )
# session.commit()
# '''
# 多个复合条件:
# filter( 条件1,条件2,条件3.. ) # and的关系
#
# filter( or_( 条件1,条件2), not_(条件2),and_(条件1,条件2) )
#
# session.query(表模型).filter(条件1).filter(条件2).filter(条件3) 条件可以拼接成and的关系
#
# or_: 函数里的条件都是 or 的关系
# and_: 函数里的条件是 and 的关系
# not_ : 将条件的结果进行取反
# '''
#
# # 五、【表数据的删除】
# try:
# session.query( User ).filter( User.username == '清风飞扬' ).delete() # 只要命中就删除
# session.commit()
# except:
# session.rollback() # 如果报错,就回滚
#
# # 清空数据,并且重置自增主键 truncate table 表名; 无法回滚
# # session.execute( text( "truncate table user_info_detail" ) ) # 直接书写原生的sql语句
# # 可以select、update、delete全部支持
#
# '''1.单表基础查询'''
# # ① 单条数据查询 first(),返回的是一个查询结果对象
# r1 = session.query(User).first()
# print('获取单个查询结果对象:',r1)
# print(r1.id,r1.usernmae,r1.create_date,r1.update_date)
#
# # ② 全量查询 all() , 返回的是一个列表list
# r2 = session.query(User).all()
# print('获取多个查询结果对象:',r2)
# for i in range( len(r2) ):
# print(f'第{i+1}行数据:',r2[i].id,r2[i].usernmae,r2[i].create_date,r2[i].update_date)
#
# q = session.query(User) # 得到一个查询语句对象
# r3 = q.all() # 获取查询语句对象的所有内容
# print(q)
# print(r3)
#
# # ③ where 条件查询
# r4 = session.query(User).filter( or_(User.id == 1, User.usernmae == '李四') ).all()
# for i in r4:
# print(i.id,i.usernmae)
#
# # ④ like模糊匹配查询
# r5 = session.query(User).where( User.usernmae.like('%三%') ).all()
# for i in r5:
# print('like模糊匹配:',i.id, i.usernmae)
#
# # ⑤ order by排序
# r5 = session.query(User).order_by(User.id.desc(), User.usernmae).all()
# for i in r5:
# print('排序:', i.id, i.usernmae)
#
# # ⑥ limit 分页
# '''
# 分页公式:
# 原生sql:limit( (页数-1)*每页数据量, 每页数据量 )
# orm里: offset( (页数-1)*每页数据量 ).limit(每页数据量)
# '''
# n = 1 # 页数
# m = 2 # 每页数据量
#
# r6 = session.query(User).offset((n-1)*m).limit(m).all()
# for i in r6:
# print('分页:', i.id, i.usernmae)
#
# '''2.分组聚合group by'''
# '''
# select usernmae,count(1)
# from user_info_detail
# group by usernmae
# having count(1) >= 2
# '''
# r7 = session.query(User.usernmae,func.count(User.id).label('num')).\
# group_by( User.usernmae ).\
# having( func.count(User.id) >= 2 ).\
# all()
#
# for i in r7:
# print('分组聚合:',i.usernmae,i.num)
#
# '''
# func函数支持:max、min、sum、count、avg常用的聚合函数
# 用法: func.count(聚合的字段)
# '''
#
# '''3.多表关联查询join内连接/outerjoin左连接'''
# r8 = session.query(User.id.label('user_id') , User.usernmae, Order.id.label('order_id'), Order.title ).\
# join( Order, User.id == Order.userid ).\
# order_by(User.id).\
# all()
#
# for i in r8:
# print('多表关联内连接:',i.user_id,i.usernmae,i.order_id,i.title)
#
# # outerjoin(谁放在里面,谁就是从表)
# r8 = session.query(User.id.label('user_id') , User.usernmae, Order.id.label('order_id'), Order.title ).\
# outerjoin( Order, User.id == Order.userid ).\
# order_by(User.id).\
# all()
#
# for i in r8:
# print('多表关联左连接:',i.user_id,i.usernmae,i.order_id,i.title)
#
# '''
# select ——> session.query( 表模型名 )
# from 表1
# join 表2 on 条件 ——> join(连接的表,条件) / outerjoin(连接的表,条件)
# where 筛选条件 ——> filter(条件)
# group by 分组字段 ——> group_by(分组的字段)
# having 分组后过滤 ——> having(过滤的条件)
# order by 排序 ——> order_by( 排序的字段.desc() )
# limit 分页 ——> offset(偏移量).limit(数据量)
# '''
#
# n = 1 # 页数
# m = 2 # 每页数据量
# r9 = session.query(User.usernmae,Order.title,func.count(1).label('ordernum')).\
# join(Order,User.id == Order.userid).\
# filter(Order.title == '苹果').\
# group_by(User.usernmae,Order.title).\
# having(func.count(1) >= 1).\
# order_by(func.count(1).desc()).\
# offset((n-1)*m).limit(m).\
# all()
#
# for i in r9:
# print('完整的查询:',i.usernmae,i.title,i.ordernum)
#
#
#
View File
+540
View File
@@ -0,0 +1,540 @@
2026-09-21 08:00:49 - ai-model - INFO - ai-model - 0
2026-09-21 08:00:49 - ai-model - INFO - ai-model - 1
2026-09-21 08:00:50 - ai-model - INFO - ai-model - 0
2026-09-21 08:00:50 - ai-model - INFO - ai-model - 1
2026-09-21 08:00:51 - ai-model - INFO - ai-model - 0
2026-09-21 08:00:51 - ai-model - INFO - ai-model - 1
2026-09-21 08:00:52 - ai-model - INFO - ai-model - 0
2026-09-21 08:00:52 - ai-model - INFO - ai-model - 1
2026-09-21 08:04:03 - ai-model - INFO - ai-model - 0
2026-09-21 08:04:03 - ai-model - INFO - ai-model - 1
2026-09-21 08:36:33 - ai-model - INFO - ai-model - 0
2026-09-21 08:36:33 - ai-model - INFO - ai-model - 1
2026-09-21 08:36:34 - ai-model - INFO - ai-model - 0
2026-09-21 08:36:34 - ai-model - INFO - ai-model - 1
2026-09-21 08:36:38 - ai-model - INFO - ai-model - 0
2026-09-21 08:36:38 - ai-model - INFO - ai-model - 1
2026-09-21 08:36:54 - ai-model - INFO - ai-model - 0
2026-09-21 08:36:54 - ai-model - INFO - ai-model - 1
2026-09-21 08:36:55 - ai-model - INFO - ai-model - 0
2026-09-21 08:36:55 - ai-model - INFO - ai-model - 1
2026-09-21 08:37:47 - ai-model - INFO - ai-model - 0
2026-09-21 08:37:47 - ai-model - INFO - ai-model - 1
2026-09-21 08:38:00 - ai-model - INFO - ai-model - 0
2026-09-21 08:38:00 - ai-model - INFO - ai-model - 1
2026-09-21 08:39:08 - ai-model - INFO - ai-model - 0
2026-09-21 08:39:08 - ai-model - INFO - ai-model - 1
2026-09-21 08:39:09 - ai-model - INFO - ai-model - 0
2026-09-21 08:39:09 - ai-model - INFO - ai-model - 1
2026-09-21 08:41:18 - ai-model - INFO - ai-model - 0
2026-09-21 08:41:18 - ai-model - INFO - ai-model - 1
2026-09-21 08:41:37 - ai-model - INFO - ai-model - 0
2026-09-21 08:41:37 - ai-model - INFO - ai-model - 1
2026-09-21 08:41:38 - ai-model - INFO - ai-model - 0
2026-09-21 08:41:38 - ai-model - INFO - ai-model - 1
2026-09-21 08:50:09 - ai-model - INFO - ai-model - 0
2026-09-21 08:50:09 - ai-model - INFO - ai-model - 1
2026-09-21 08:50:10 - ai-model - INFO - ai-model - 0
2026-09-21 08:50:10 - ai-model - INFO - ai-model - 1
2026-09-21 08:50:22 - ai-model - INFO - ai-model - 0
2026-09-21 08:50:22 - ai-model - INFO - ai-model - 1
2026-09-21 08:50:29 - ai-model - INFO - ai-model - 0
2026-09-21 08:50:29 - ai-model - INFO - ai-model - 1
2026-09-21 08:50:30 - ai-model - INFO - ai-model - 0
2026-09-21 08:50:30 - ai-model - INFO - ai-model - 1
2026-09-21 10:56:59 - ai-model - INFO - ai-model - 0
2026-09-21 10:56:59 - ai-model - INFO - ai-model - 1
2026-09-21 10:57:12 - ai-model - INFO - ai-model - 0
2026-09-21 10:57:12 - ai-model - INFO - ai-model - 1
2026-09-21 10:57:14 - ai-model - INFO - ai-model - 0
2026-09-21 10:57:14 - ai-model - INFO - ai-model - 1
2026-09-21 10:57:46 - ai-model - INFO - ai-model - 0
2026-09-21 10:57:46 - ai-model - INFO - ai-model - 1
2026-09-21 10:57:50 - ai-model - INFO - ai-model - 0
2026-09-21 10:57:50 - ai-model - INFO - ai-model - 1
2026-09-21 10:57:51 - ai-model - INFO - ai-model - 0
2026-09-21 10:57:51 - ai-model - INFO - ai-model - 1
2026-09-21 10:58:19 - ai-model - INFO - ai-model - 0
2026-09-21 10:58:19 - ai-model - INFO - ai-model - 1
2026-09-21 10:58:20 - ai-model - INFO - ai-model - 0
2026-09-21 10:58:20 - ai-model - INFO - ai-model - 1
2026-09-21 10:58:43 - ai-model - INFO - ai-model - 0
2026-09-21 10:58:43 - ai-model - INFO - ai-model - 1
2026-09-21 10:58:44 - ai-model - INFO - ai-model - 0
2026-09-21 10:58:44 - ai-model - INFO - ai-model - 1
2026-09-21 10:58:47 - ai-model - INFO - ai-model - 0
2026-09-21 10:58:47 - ai-model - INFO - ai-model - 1
2026-09-21 10:59:52 - ai-model - INFO - ai-model - 0
2026-09-21 10:59:52 - ai-model - INFO - ai-model - 1
2026-09-21 10:59:58 - ai-model - INFO - ai-model - 0
2026-09-21 10:59:58 - ai-model - INFO - ai-model - 1
2026-09-21 11:00:08 - ai-model - INFO - ai-model - 0
2026-09-21 11:00:08 - ai-model - INFO - ai-model - 1
2026-09-21 11:00:24 - ai-model - INFO - ai-model - 0
2026-09-21 11:00:24 - ai-model - INFO - ai-model - 1
2026-09-21 11:00:25 - ai-model - INFO - ai-model - 0
2026-09-21 11:00:25 - ai-model - INFO - ai-model - 1
2026-09-21 11:00:26 - ai-model - INFO - ai-model - 0
2026-09-21 11:00:26 - ai-model - INFO - ai-model - 1
2026-09-21 11:00:27 - ai-model - INFO - ai-model - 0
2026-09-21 11:00:27 - ai-model - INFO - ai-model - 1
2026-09-21 11:00:30 - ai-model - INFO - ai-model - 0
2026-09-21 11:00:30 - ai-model - INFO - ai-model - 1
2026-09-21 11:00:31 - ai-model - INFO - ai-model - 0
2026-09-21 11:00:31 - ai-model - INFO - ai-model - 1
2026-09-21 11:02:13 - ai-model - INFO - ai-model - 0
2026-09-21 11:02:13 - ai-model - INFO - ai-model - 1
2026-09-21 11:02:14 - ai-model - INFO - ai-model - 0
2026-09-21 11:02:14 - ai-model - INFO - ai-model - 1
2026-09-21 11:03:33 - ai-model - INFO - ai-model - 0
2026-09-21 11:03:33 - ai-model - INFO - ai-model - 1
2026-09-21 11:03:34 - ai-model - INFO - ai-model - 0
2026-09-21 11:03:34 - ai-model - INFO - ai-model - 1
2026-09-21 11:03:46 - ai-model - INFO - ai-model - 0
2026-09-21 11:03:46 - ai-model - INFO - ai-model - 1
2026-09-21 11:04:05 - ai-model - INFO - ai-model - 0
2026-09-21 11:04:05 - ai-model - INFO - ai-model - 1
2026-09-21 11:05:31 - ai-model - INFO - ai-model - 0
2026-09-21 11:05:31 - ai-model - INFO - ai-model - 1
2026-09-21 11:05:45 - ai-model - INFO - ai-model - 0
2026-09-21 11:05:45 - ai-model - INFO - ai-model - 1
2026-09-21 11:05:46 - ai-model - INFO - ai-model - 0
2026-09-21 11:05:46 - ai-model - INFO - ai-model - 1
2026-09-21 11:08:10 - ai-model - INFO - ai-model - 0
2026-09-21 11:08:10 - ai-model - INFO - ai-model - 1
2026-09-21 11:08:24 - ai-model - INFO - ai-model - 0
2026-09-21 11:08:24 - ai-model - INFO - ai-model - 1
2026-09-21 11:08:24 - ai-model - INFO - ai-model - 0
2026-09-21 11:08:24 - ai-model - INFO - ai-model - 1
2026-09-21 11:08:56 - ai-model - INFO - ai-model - 0
2026-09-21 11:08:56 - ai-model - INFO - ai-model - 1
2026-09-21 11:08:57 - ai-model - INFO - ai-model - 0
2026-09-21 11:08:57 - ai-model - INFO - ai-model - 1
2026-09-21 11:10:12 - ai-model - INFO - ai-model - 0
2026-09-21 11:10:12 - ai-model - INFO - ai-model - 1
2026-09-21 11:10:41 - ai-model - INFO - ai-model - 0
2026-09-21 11:10:41 - ai-model - INFO - ai-model - 1
2026-09-21 11:10:42 - ai-model - INFO - ai-model - 0
2026-09-21 11:10:42 - ai-model - INFO - ai-model - 1
2026-09-21 11:11:00 - ai-model - INFO - ai-model - 0
2026-09-21 11:11:00 - ai-model - INFO - ai-model - 1
2026-09-21 11:11:01 - ai-model - INFO - ai-model - 0
2026-09-21 11:11:01 - ai-model - INFO - ai-model - 1
2026-09-21 11:12:03 - ai-model - INFO - ai-model - 0
2026-09-21 11:12:03 - ai-model - INFO - ai-model - 1
2026-09-21 11:12:04 - ai-model - INFO - ai-model - 0
2026-09-21 11:12:04 - ai-model - INFO - ai-model - 1
2026-09-21 11:12:59 - ai-model - INFO - ai-model - 0
2026-09-21 11:12:59 - ai-model - INFO - ai-model - 1
2026-09-21 11:13:00 - ai-model - INFO - ai-model - 0
2026-09-21 11:13:00 - ai-model - INFO - ai-model - 1
2026-09-21 11:13:44 - ai-model - INFO - ai-model - 0
2026-09-21 11:13:44 - ai-model - INFO - ai-model - 1
2026-09-21 11:13:45 - ai-model - INFO - ai-model - 0
2026-09-21 11:13:45 - ai-model - INFO - ai-model - 1
2026-09-21 11:13:49 - ai-model - INFO - ai-model - 0
2026-09-21 11:13:49 - ai-model - INFO - ai-model - 1
2026-09-21 11:13:56 - ai-model - INFO - ai-model - 0
2026-09-21 11:13:56 - ai-model - INFO - ai-model - 1
2026-09-21 11:13:57 - ai-model - INFO - ai-model - 0
2026-09-21 11:13:57 - ai-model - INFO - ai-model - 1
2026-09-23 13:14:24 - ai-model - INFO - ai-model - 0
2026-09-23 13:14:24 - ai-model - INFO - ai-model - 1
2026-09-23 13:14:32 - ai-model - INFO - ai-model - 0
2026-09-23 13:14:32 - ai-model - INFO - ai-model - 1
2026-09-23 13:16:42 - ai-model - INFO - ai-model - 0
2026-09-23 13:16:42 - ai-model - INFO - ai-model - 1
2026-09-23 14:43:37 - ai-model - INFO - ai-model - 0
2026-09-23 14:43:37 - ai-model - INFO - ai-model - 1
2026-09-23 14:43:43 - ai-model - INFO - ai-model - 0
2026-09-23 14:43:43 - ai-model - INFO - ai-model - 1
2026-09-23 14:43:44 - ai-model - INFO - ai-model - 0
2026-09-23 14:43:44 - ai-model - INFO - ai-model - 1
2026-09-23 14:43:57 - ai-model - INFO - ai-model - 0
2026-09-23 14:43:57 - ai-model - INFO - ai-model - 1
2026-09-23 14:44:20 - ai-model - INFO - ai-model - 0
2026-09-23 14:44:20 - ai-model - INFO - ai-model - 1
2026-09-23 14:44:21 - ai-model - INFO - ai-model - 0
2026-09-23 14:44:21 - ai-model - INFO - ai-model - 1
2026-09-23 14:45:04 - ai-model - INFO - ai-model - 0
2026-09-23 14:45:04 - ai-model - INFO - ai-model - 1
2026-09-23 14:45:05 - ai-model - INFO - ai-model - 0
2026-09-23 14:45:05 - ai-model - INFO - ai-model - 1
2026-09-23 14:45:37 - ai-model - INFO - ai-model - 0
2026-09-23 14:45:37 - ai-model - INFO - ai-model - 1
2026-09-23 14:46:19 - ai-model - INFO - ai-model - 0
2026-09-23 14:46:19 - ai-model - INFO - ai-model - 1
2026-09-23 14:47:59 - ai-model - INFO - ai-model - 0
2026-09-23 14:47:59 - ai-model - INFO - ai-model - 1
2026-09-23 14:48:21 - ai-model - INFO - ai-model - 0
2026-09-23 14:48:21 - ai-model - INFO - ai-model - 1
2026-09-23 14:48:38 - ai-model - INFO - ai-model - 0
2026-09-23 14:48:38 - ai-model - INFO - ai-model - 1
2026-09-23 14:48:46 - ai-model - INFO - ai-model - 0
2026-09-23 14:48:46 - ai-model - INFO - ai-model - 1
2026-09-23 14:48:56 - ai-model - INFO - ai-model - 0
2026-09-23 14:48:56 - ai-model - INFO - ai-model - 1
2026-09-23 14:49:05 - ai-model - INFO - ai-model - 0
2026-09-23 14:49:05 - ai-model - INFO - ai-model - 1
2026-09-23 14:49:15 - ai-model - INFO - ai-model - 0
2026-09-23 14:49:15 - ai-model - INFO - ai-model - 1
2026-09-23 14:49:31 - ai-model - INFO - ai-model - 0
2026-09-23 14:49:31 - ai-model - INFO - ai-model - 1
2026-09-23 14:58:15 - ai-model - INFO - ai-model - 0
2026-09-23 14:58:15 - ai-model - INFO - ai-model - 1
2026-09-23 14:58:16 - ai-model - INFO - ai-model - 0
2026-09-23 14:58:16 - ai-model - INFO - ai-model - 1
2026-09-23 15:00:05 - ai-model - INFO - ai-model - 0
2026-09-23 15:00:05 - ai-model - INFO - ai-model - 1
2026-09-23 15:00:06 - ai-model - INFO - ai-model - 0
2026-09-23 15:00:06 - ai-model - INFO - ai-model - 1
2026-09-23 15:00:25 - ai-model - INFO - ai-model - 0
2026-09-23 15:00:25 - ai-model - INFO - ai-model - 1
2026-09-23 15:00:26 - ai-model - INFO - ai-model - 0
2026-09-23 15:00:26 - ai-model - INFO - ai-model - 1
2026-09-23 15:00:54 - ai-model - INFO - ai-model - 0
2026-09-23 15:00:54 - ai-model - INFO - ai-model - 1
2026-09-23 15:01:02 - ai-model - INFO - ai-model - 0
2026-09-23 15:01:02 - ai-model - INFO - ai-model - 1
2026-09-23 15:01:30 - ai-model - INFO - ai-model - 0
2026-09-23 15:01:30 - ai-model - INFO - ai-model - 1
2026-09-23 15:01:38 - ai-model - INFO - ai-model - 0
2026-09-23 15:01:38 - ai-model - INFO - ai-model - 1
2026-09-23 15:02:13 - ai-model - INFO - ai-model - 0
2026-09-23 15:02:13 - ai-model - INFO - ai-model - 1
2026-09-23 15:02:46 - ai-model - INFO - ai-model - 0
2026-09-23 15:02:46 - ai-model - INFO - ai-model - 1
2026-09-23 15:02:48 - ai-model - INFO - ai-model - 0
2026-09-23 15:02:48 - ai-model - INFO - ai-model - 1
2026-09-23 15:14:20 - ai-model - INFO - ai-model - 0
2026-09-23 15:14:20 - ai-model - INFO - ai-model - 1
2026-09-23 15:14:29 - ai-model - INFO - ai-model - 0
2026-09-23 15:14:29 - ai-model - INFO - ai-model - 1
2026-09-23 15:14:31 - ai-model - INFO - ai-model - 0
2026-09-23 15:14:31 - ai-model - INFO - ai-model - 1
2026-09-23 15:14:47 - ai-model - INFO - ai-model - 0
2026-09-23 15:14:47 - ai-model - INFO - ai-model - 1
2026-09-23 15:14:48 - ai-model - INFO - ai-model - 0
2026-09-23 15:14:48 - ai-model - INFO - ai-model - 1
2026-09-23 15:25:54 - ai-model - INFO - ai-model - 0
2026-09-23 15:25:54 - ai-model - INFO - ai-model - 1
2026-09-23 15:26:19 - ai-model - INFO - ai-model - 0
2026-09-23 15:26:19 - ai-model - INFO - ai-model - 1
2026-09-23 15:29:43 - ai-model - INFO - ai-model - 0
2026-09-23 15:29:43 - ai-model - INFO - ai-model - 1
2026-09-23 15:31:57 - ai-model - INFO - ai-model - 0
2026-09-23 15:31:57 - ai-model - INFO - ai-model - 1
2026-09-23 15:32:22 - ai-model - INFO - ai-model - 0
2026-09-23 15:32:22 - ai-model - INFO - ai-model - 1
2026-09-23 15:32:29 - ai-model - INFO - ai-model - 0
2026-09-23 15:32:29 - ai-model - INFO - ai-model - 1
2026-09-23 15:32:45 - ai-model - INFO - ai-model - 0
2026-09-23 15:32:45 - ai-model - INFO - ai-model - 1
2026-09-23 15:32:54 - ai-model - INFO - ai-model - 0
2026-09-23 15:32:54 - ai-model - INFO - ai-model - 1
2026-09-23 15:33:23 - ai-model - INFO - ai-model - 0
2026-09-23 15:33:23 - ai-model - INFO - ai-model - 1
2026-09-23 15:33:39 - ai-model - INFO - ai-model - 0
2026-09-23 15:33:39 - ai-model - INFO - ai-model - 1
2026-09-23 15:33:41 - ai-model - INFO - ai-model - 0
2026-09-23 15:33:41 - ai-model - INFO - ai-model - 1
2026-09-23 15:33:53 - ai-model - INFO - ai-model - 0
2026-09-23 15:33:53 - ai-model - INFO - ai-model - 1
2026-09-23 15:33:54 - ai-model - INFO - ai-model - 0
2026-09-23 15:33:54 - ai-model - INFO - ai-model - 1
2026-09-23 15:34:02 - ai-model - INFO - ai-model - 0
2026-09-23 15:34:02 - ai-model - INFO - ai-model - 1
2026-09-23 15:34:03 - ai-model - INFO - ai-model - 0
2026-09-23 15:34:03 - ai-model - INFO - ai-model - 1
2026-09-23 15:34:15 - ai-model - INFO - ai-model - 0
2026-09-23 15:34:15 - ai-model - INFO - ai-model - 1
2026-09-23 15:34:22 - ai-model - INFO - ai-model - 0
2026-09-23 15:34:22 - ai-model - INFO - ai-model - 1
2026-09-23 15:34:23 - ai-model - INFO - ai-model - 0
2026-09-23 15:34:23 - ai-model - INFO - ai-model - 1
2026-09-23 15:34:35 - ai-model - INFO - ai-model - 0
2026-09-23 15:34:35 - ai-model - INFO - ai-model - 1
2026-09-23 15:35:05 - ai-model - INFO - ai-model - 0
2026-09-23 15:35:05 - ai-model - INFO - ai-model - 1
2026-09-23 15:35:12 - ai-model - INFO - ai-model - 0
2026-09-23 15:35:12 - ai-model - INFO - ai-model - 1
2026-09-23 15:35:16 - ai-model - INFO - ai-model - 0
2026-09-23 15:35:16 - ai-model - INFO - ai-model - 1
2026-09-23 15:35:17 - ai-model - INFO - ai-model - 0
2026-09-23 15:35:17 - ai-model - INFO - ai-model - 1
2026-09-23 15:35:34 - ai-model - INFO - ai-model - 0
2026-09-23 15:35:34 - ai-model - INFO - ai-model - 1
2026-09-23 15:35:36 - ai-model - INFO - ai-model - 0
2026-09-23 15:35:36 - ai-model - INFO - ai-model - 1
2026-09-23 15:35:41 - ai-model - INFO - ai-model - 0
2026-09-23 15:35:41 - ai-model - INFO - ai-model - 1
2026-09-23 15:35:42 - ai-model - INFO - ai-model - 0
2026-09-23 15:35:42 - ai-model - INFO - ai-model - 1
2026-09-23 15:44:26 - ai-model - INFO - ai-model - 0
2026-09-23 15:44:26 - ai-model - INFO - ai-model - 1
2026-09-23 15:44:28 - ai-model - INFO - ai-model - 0
2026-09-23 15:44:28 - ai-model - INFO - ai-model - 1
2026-09-23 15:44:32 - ai-model - INFO - ai-model - 0
2026-09-23 15:44:32 - ai-model - INFO - ai-model - 1
2026-09-23 15:44:34 - ai-model - INFO - ai-model - 0
2026-09-23 15:44:34 - ai-model - INFO - ai-model - 1
2026-09-23 15:44:35 - ai-model - INFO - ai-model - 0
2026-09-23 15:44:35 - ai-model - INFO - ai-model - 1
2026-09-23 15:44:50 - ai-model - INFO - ai-model - 0
2026-09-23 15:44:50 - ai-model - INFO - ai-model - 1
2026-09-23 15:44:51 - ai-model - INFO - ai-model - 0
2026-09-23 15:44:51 - ai-model - INFO - ai-model - 1
2026-09-23 15:45:24 - ai-model - INFO - ai-model - 0
2026-09-23 15:45:24 - ai-model - INFO - ai-model - 1
2026-09-23 15:45:25 - ai-model - INFO - ai-model - 0
2026-09-23 15:45:25 - ai-model - INFO - ai-model - 1
2026-09-23 15:45:29 - ai-model - INFO - ai-model - 0
2026-09-23 15:45:29 - ai-model - INFO - ai-model - 1
2026-09-23 15:45:42 - ai-model - INFO - ai-model - 0
2026-09-23 15:45:42 - ai-model - INFO - ai-model - 1
2026-09-23 15:45:43 - ai-model - INFO - ai-model - 0
2026-09-23 15:45:43 - ai-model - INFO - ai-model - 1
2026-09-23 15:45:46 - ai-model - INFO - ai-model - 0
2026-09-23 15:45:46 - ai-model - INFO - ai-model - 1
2026-09-23 15:45:47 - ai-model - INFO - ai-model - 0
2026-09-23 15:45:47 - ai-model - INFO - ai-model - 1
2026-09-23 15:46:25 - ai-model - INFO - ai-model - 0
2026-09-23 15:46:25 - ai-model - INFO - ai-model - 1
2026-09-23 15:46:26 - ai-model - INFO - ai-model - 0
2026-09-23 15:46:26 - ai-model - INFO - ai-model - 1
2026-09-23 15:46:33 - ai-model - INFO - ai-model - 0
2026-09-23 15:46:33 - ai-model - INFO - ai-model - 1
2026-09-23 15:46:34 - ai-model - INFO - ai-model - 0
2026-09-23 15:46:34 - ai-model - INFO - ai-model - 1
2026-09-23 15:46:41 - ai-model - INFO - ai-model - 0
2026-09-23 15:46:41 - ai-model - INFO - ai-model - 1
2026-09-23 15:46:48 - ai-model - INFO - ai-model - 0
2026-09-23 15:46:48 - ai-model - INFO - ai-model - 1
2026-09-23 15:46:56 - ai-model - INFO - ai-model - 0
2026-09-23 15:46:56 - ai-model - INFO - ai-model - 1
2026-09-23 15:47:31 - ai-model - INFO - ai-model - 0
2026-09-23 15:47:31 - ai-model - INFO - ai-model - 1
2026-09-23 15:47:48 - ai-model - INFO - ai-model - 0
2026-09-23 15:47:48 - ai-model - INFO - ai-model - 1
2026-09-23 15:48:10 - ai-model - INFO - ai-model - 0
2026-09-23 15:48:10 - ai-model - INFO - ai-model - 1
2026-09-23 15:48:11 - ai-model - INFO - ai-model - 0
2026-09-23 15:48:11 - ai-model - INFO - ai-model - 1
2026-09-23 15:48:20 - ai-model - INFO - ai-model - 0
2026-09-23 15:48:20 - ai-model - INFO - ai-model - 1
2026-09-23 15:48:33 - ai-model - INFO - ai-model - 0
2026-09-23 15:48:33 - ai-model - INFO - ai-model - 1
2026-09-23 15:48:35 - ai-model - INFO - ai-model - 0
2026-09-23 15:48:35 - ai-model - INFO - ai-model - 1
2026-09-23 15:48:56 - ai-model - INFO - ai-model - 0
2026-09-23 15:48:56 - ai-model - INFO - ai-model - 1
2026-09-23 15:49:03 - ai-model - INFO - ai-model - 0
2026-09-23 15:49:03 - ai-model - INFO - ai-model - 1
2026-09-23 15:49:04 - ai-model - INFO - ai-model - 0
2026-09-23 15:49:04 - ai-model - INFO - ai-model - 1
2026-09-23 15:49:05 - ai-model - INFO - ai-model - 0
2026-09-23 15:49:05 - ai-model - INFO - ai-model - 1
2026-09-23 15:49:20 - ai-model - INFO - ai-model - 0
2026-09-23 15:49:20 - ai-model - INFO - ai-model - 1
2026-09-23 15:50:11 - ai-model - INFO - ai-model - 0
2026-09-23 15:50:11 - ai-model - INFO - ai-model - 1
2026-09-23 15:50:15 - ai-model - INFO - ai-model - 0
2026-09-23 15:50:15 - ai-model - INFO - ai-model - 1
2026-09-23 15:52:02 - ai-model - INFO - ai-model - 0
2026-09-23 15:52:02 - ai-model - INFO - ai-model - 1
2026-09-23 15:52:03 - ai-model - INFO - ai-model - 0
2026-09-23 15:52:03 - ai-model - INFO - ai-model - 1
2026-09-23 15:52:49 - ai-model - INFO - ai-model - 0
2026-09-23 15:52:49 - ai-model - INFO - ai-model - 1
2026-09-23 15:52:51 - ai-model - INFO - ai-model - 0
2026-09-23 15:52:51 - ai-model - INFO - ai-model - 1
2026-09-23 15:53:35 - ai-model - INFO - ai-model - 0
2026-09-23 15:53:35 - ai-model - INFO - ai-model - 1
2026-09-23 15:53:44 - ai-model - INFO - ai-model - 0
2026-09-23 15:53:44 - ai-model - INFO - ai-model - 1
2026-09-23 15:53:46 - ai-model - INFO - ai-model - 0
2026-09-23 15:53:46 - ai-model - INFO - ai-model - 1
2026-09-23 15:54:04 - ai-model - INFO - ai-model - 0
2026-09-23 15:54:04 - ai-model - INFO - ai-model - 1
2026-09-23 15:54:06 - ai-model - INFO - ai-model - 0
2026-09-23 15:54:06 - ai-model - INFO - ai-model - 1
2026-09-23 15:54:18 - ai-model - INFO - ai-model - 0
2026-09-23 15:54:18 - ai-model - INFO - ai-model - 1
2026-09-23 15:54:22 - ai-model - INFO - ai-model - 0
2026-09-23 15:54:22 - ai-model - INFO - ai-model - 1
2026-09-23 15:54:24 - ai-model - INFO - ai-model - 0
2026-09-23 15:54:24 - ai-model - INFO - ai-model - 1
2026-09-23 15:54:26 - ai-model - INFO - ai-model - 0
2026-09-23 15:54:26 - ai-model - INFO - ai-model - 1
2026-09-23 15:54:49 - ai-model - INFO - ai-model - 0
2026-09-23 15:54:49 - ai-model - INFO - ai-model - 1
2026-09-23 15:54:55 - ai-model - INFO - ai-model - 0
2026-09-23 15:54:55 - ai-model - INFO - ai-model - 1
2026-09-23 15:54:57 - ai-model - INFO - ai-model - 0
2026-09-23 15:54:57 - ai-model - INFO - ai-model - 1
2026-09-23 15:54:58 - ai-model - INFO - ai-model - 0
2026-09-23 15:54:58 - ai-model - INFO - ai-model - 1
2026-09-23 15:54:59 - ai-model - INFO - ai-model - 0
2026-09-23 15:54:59 - ai-model - INFO - ai-model - 1
2026-09-23 15:55:00 - ai-model - INFO - ai-model - 0
2026-09-23 15:55:00 - ai-model - INFO - ai-model - 1
2026-09-23 15:55:44 - ai-model - INFO - ai-model - 0
2026-09-23 15:55:44 - ai-model - INFO - ai-model - 1
2026-09-23 15:55:46 - ai-model - INFO - ai-model - 0
2026-09-23 15:55:46 - ai-model - INFO - ai-model - 1
2026-09-23 15:55:53 - ai-model - INFO - ai-model - 0
2026-09-23 15:55:53 - ai-model - INFO - ai-model - 1
2026-09-23 15:55:54 - ai-model - INFO - ai-model - 0
2026-09-23 15:55:54 - ai-model - INFO - ai-model - 1
2026-09-23 15:56:19 - ai-model - INFO - ai-model - 0
2026-09-23 15:56:19 - ai-model - INFO - ai-model - 1
2026-09-23 15:56:20 - ai-model - INFO - ai-model - 0
2026-09-23 15:56:20 - ai-model - INFO - ai-model - 1
2026-09-23 15:56:30 - ai-model - INFO - ai-model - 0
2026-09-23 15:56:30 - ai-model - INFO - ai-model - 1
2026-09-23 15:56:31 - ai-model - INFO - ai-model - 0
2026-09-23 15:56:31 - ai-model - INFO - ai-model - 1
2026-09-23 15:56:43 - ai-model - INFO - ai-model - 0
2026-09-23 15:56:43 - ai-model - INFO - ai-model - 1
2026-09-23 15:56:44 - ai-model - INFO - ai-model - 0
2026-09-23 15:56:44 - ai-model - INFO - ai-model - 1
2026-09-23 15:56:47 - ai-model - INFO - ai-model - 0
2026-09-23 15:56:47 - ai-model - INFO - ai-model - 1
2026-09-23 15:56:49 - ai-model - INFO - ai-model - 0
2026-09-23 15:56:49 - ai-model - INFO - ai-model - 1
2026-09-23 15:56:52 - ai-model - INFO - ai-model - 0
2026-09-23 15:56:52 - ai-model - INFO - ai-model - 1
2026-09-23 15:56:53 - ai-model - INFO - ai-model - 0
2026-09-23 15:56:53 - ai-model - INFO - ai-model - 1
2026-09-23 15:56:54 - ai-model - INFO - ai-model - 0
2026-09-23 15:56:54 - ai-model - INFO - ai-model - 1
2026-09-23 15:57:47 - ai-model - INFO - ai-model - 0
2026-09-23 15:57:47 - ai-model - INFO - ai-model - 1
2026-09-23 15:57:48 - ai-model - INFO - ai-model - 0
2026-09-23 15:57:48 - ai-model - INFO - ai-model - 1
2026-09-23 15:58:12 - ai-model - INFO - ai-model - 0
2026-09-23 15:58:12 - ai-model - INFO - ai-model - 1
2026-09-23 15:58:13 - ai-model - INFO - ai-model - 0
2026-09-23 15:58:13 - ai-model - INFO - ai-model - 1
2026-09-23 15:58:34 - ai-model - INFO - ai-model - 0
2026-09-23 15:58:34 - ai-model - INFO - ai-model - 1
2026-09-23 15:58:36 - ai-model - INFO - ai-model - 0
2026-09-23 15:58:36 - ai-model - INFO - ai-model - 1
2026-09-23 15:59:46 - ai-model - INFO - ai-model - 0
2026-09-23 15:59:46 - ai-model - INFO - ai-model - 1
2026-09-23 16:01:33 - ai-model - INFO - ai-model - 0
2026-09-23 16:01:33 - ai-model - INFO - ai-model - 1
2026-09-23 16:01:34 - ai-model - INFO - ai-model - 0
2026-09-23 16:01:34 - ai-model - INFO - ai-model - 1
2026-09-23 16:05:56 - ai-model - INFO - ai-model - 0
2026-09-23 16:05:56 - ai-model - INFO - ai-model - 1
2026-09-23 16:05:57 - ai-model - INFO - ai-model - 0
2026-09-23 16:05:57 - ai-model - INFO - ai-model - 1
2026-09-23 16:06:05 - ai-model - INFO - ai-model - 0
2026-09-23 16:06:05 - ai-model - INFO - ai-model - 1
2026-09-23 16:06:31 - ai-model - INFO - ai-model - 0
2026-09-23 16:06:31 - ai-model - INFO - ai-model - 1
2026-09-23 16:07:02 - ai-model - INFO - ai-model - 0
2026-09-23 16:07:02 - ai-model - INFO - ai-model - 1
2026-09-23 16:08:06 - ai-model - INFO - ai-model - 0
2026-09-23 16:08:06 - ai-model - INFO - ai-model - 1
2026-09-23 16:08:49 - ai-model - INFO - ai-model - 0
2026-09-23 16:08:49 - ai-model - INFO - ai-model - 1
2026-09-23 16:09:24 - ai-model - INFO - ai-model - 0
2026-09-23 16:09:24 - ai-model - INFO - ai-model - 1
2026-09-23 16:10:02 - ai-model - INFO - ai-model - 0
2026-09-23 16:10:02 - ai-model - INFO - ai-model - 1
2026-09-23 16:10:03 - ai-model - INFO - ai-model - 0
2026-09-23 16:10:03 - ai-model - INFO - ai-model - 1
2026-09-23 16:10:06 - ai-model - INFO - ai-model - 0
2026-09-23 16:10:06 - ai-model - INFO - ai-model - 1
2026-09-23 16:11:59 - ai-model - INFO - ai-model - 0
2026-09-23 16:11:59 - ai-model - INFO - ai-model - 1
2026-09-23 16:12:38 - ai-model - INFO - ai-model - 0
2026-09-23 16:12:38 - ai-model - INFO - ai-model - 1
2026-09-23 16:12:41 - ai-model - INFO - ai-model - 0
2026-09-23 16:12:41 - ai-model - INFO - ai-model - 1
2026-09-23 16:12:43 - ai-model - INFO - ai-model - 0
2026-09-23 16:12:43 - ai-model - INFO - ai-model - 1
2026-09-23 16:12:45 - ai-model - INFO - ai-model - 0
2026-09-23 16:12:45 - ai-model - INFO - ai-model - 1
2026-09-23 16:13:32 - ai-model - INFO - ai-model - 0
2026-09-23 16:13:32 - ai-model - INFO - ai-model - 1
2026-09-23 16:13:33 - ai-model - INFO - ai-model - 0
2026-09-23 16:13:33 - ai-model - INFO - ai-model - 1
2026-09-23 16:14:14 - ai-model - INFO - ai-model - 0
2026-09-23 16:14:14 - ai-model - INFO - ai-model - 1
2026-09-23 16:14:20 - ai-model - INFO - ai-model - 0
2026-09-23 16:14:20 - ai-model - INFO - ai-model - 1
2026-09-23 16:14:21 - ai-model - INFO - ai-model - 0
2026-09-23 16:14:21 - ai-model - INFO - ai-model - 1
2026-09-23 16:14:41 - ai-model - INFO - ai-model - 0
2026-09-23 16:14:41 - ai-model - INFO - ai-model - 1
2026-09-23 16:14:41 - ai-model - INFO - ai-model - 0
2026-09-23 16:14:41 - ai-model - INFO - ai-model - 1
2026-09-23 16:14:52 - ai-model - INFO - ai-model - 0
2026-09-23 16:14:52 - ai-model - INFO - ai-model - 1
2026-09-23 16:14:57 - ai-model - INFO - ai-model - 0
2026-09-23 16:14:57 - ai-model - INFO - ai-model - 1
2026-09-23 16:14:58 - ai-model - INFO - ai-model - 0
2026-09-23 16:14:58 - ai-model - INFO - ai-model - 1
2026-09-23 16:15:17 - ai-model - INFO - ai-model - 0
2026-09-23 16:15:17 - ai-model - INFO - ai-model - 1
2026-09-23 16:16:19 - ai-model - INFO - ai-model - 0
2026-09-23 16:16:19 - ai-model - INFO - ai-model - 1
2026-09-23 16:16:41 - ai-model - INFO - ai-model - 0
2026-09-23 16:16:41 - ai-model - INFO - ai-model - 1
2026-09-23 16:16:42 - ai-model - INFO - ai-model - 0
2026-09-23 16:16:42 - ai-model - INFO - ai-model - 1
2026-09-23 16:16:54 - ai-model - INFO - ai-model - 0
2026-09-23 16:16:54 - ai-model - INFO - ai-model - 1
2026-09-23 16:16:55 - ai-model - INFO - ai-model - 0
2026-09-23 16:16:55 - ai-model - INFO - ai-model - 1
2026-09-24 11:36:59 - ai-model - INFO - ai-model - 0
2026-09-24 11:36:59 - ai-model - INFO - ai-model - 1
2026-09-24 11:46:48 - ai-model - INFO - ai-model - 0
2026-09-24 11:46:49 - ai-model - INFO - ai-model - 1
2026-09-24 11:47:39 - ai-model - INFO - ai-model - 0
2026-09-24 11:47:39 - ai-model - INFO - ai-model - 1
2026-09-24 11:48:04 - ai-model - INFO - ai-model - 0
2026-09-24 11:48:04 - ai-model - INFO - ai-model - 1
2026-09-24 11:48:05 - ai-model - INFO - ai-model - 0
2026-09-24 11:48:05 - ai-model - INFO - ai-model - 1
2026-09-24 11:48:31 - ai-model - INFO - ai-model - 0
2026-09-24 11:48:31 - ai-model - INFO - ai-model - 1
2026-09-24 11:50:35 - ai-model - INFO - ai-model - 0
2026-09-24 11:50:35 - ai-model - INFO - ai-model - 1
2026-09-24 11:50:36 - ai-model - INFO - ai-model - 0
2026-09-24 11:50:36 - ai-model - INFO - ai-model - 1
2026-09-24 11:54:00 - ai-model - INFO - ai-model - 0
2026-09-24 11:54:00 - ai-model - INFO - ai-model - 1
2026-09-24 11:54:01 - ai-model - INFO - ai-model - 0
2026-09-24 11:54:01 - ai-model - INFO - ai-model - 1
2026-09-24 11:54:19 - ai-model - INFO - ai-model - 0
2026-09-24 11:54:19 - ai-model - INFO - ai-model - 1
2026-09-24 11:54:20 - ai-model - INFO - ai-model - 0
2026-09-24 11:54:20 - ai-model - INFO - ai-model - 1
2026-09-24 11:55:52 - ai-model - INFO - ai-model - 0
2026-09-24 11:55:52 - ai-model - INFO - ai-model - 1
2026-09-24 11:55:53 - ai-model - INFO - ai-model - 0
2026-09-24 11:55:53 - ai-model - INFO - ai-model - 1
2026-09-24 12:00:37 - ai-model - INFO - ai-model - 0
2026-09-24 12:00:37 - ai-model - INFO - ai-model - 1
2026-09-24 12:01:44 - ai-model - INFO - ai-model - 0
2026-09-24 12:01:44 - ai-model - INFO - ai-model - 1
2026-09-24 12:02:35 - ai-model - INFO - ai-model - 0
2026-09-24 12:02:35 - ai-model - INFO - ai-model - 1
2026-09-24 12:10:50 - ai-model - INFO - ai-model - 0
2026-09-24 12:10:50 - ai-model - INFO - ai-model - 1
2026-09-24 16:58:54 - ai-model - INFO - ai-model - 0
2026-09-24 16:58:54 - ai-model - INFO - ai-model - 1
2026-09-24 17:03:54 - ai-model - INFO - ai-model - 0
2026-09-24 17:03:54 - ai-model - INFO - ai-model - 1
2026-09-24 17:03:56 - ai-model - INFO - ai-model - 0
2026-09-24 17:03:56 - ai-model - INFO - ai-model - 1
2026-09-24 17:05:02 - ai-model - INFO - ai-model - 0
2026-09-24 17:05:02 - ai-model - INFO - ai-model - 1
2026-09-24 17:05:03 - ai-model - INFO - ai-model - 0
2026-09-24 17:05:03 - ai-model - INFO - ai-model - 1
2026-09-24 17:05:11 - ai-model - INFO - ai-model - 0
2026-09-24 17:05:11 - ai-model - INFO - ai-model - 1
+8 -4
View File
@@ -2,9 +2,9 @@ from fastapi import FastAPI,Request
from fastapi.middleware.cors import CORSMiddleware
from starlette.staticfiles import StaticFiles
from router.features import form, method, file, validation, mimetype, path_query_variables, json
from router.features import form, method, file, validation, mimetype, path_query_variables, json,session_async
from router.dbopt import mysql,order_route
from router.dbopt import mysql,order_route,order_select_rep_query
from router.workhome import wk_0915,wk_0916,wk_0917
@@ -25,9 +25,13 @@ app.include_router(form.route)
app.include_router(file.route)
app.include_router(json.route)
app.include_router(session_async.route)
app.include_router(mysql.route)
app.include_router(order_route.route)
app.include_router(order_select_rep_query.route)
# homeworks...
app.include_router(wk_0915.route)
@@ -53,8 +57,8 @@ app.add_middleware(
)
from middle import middles
app.middleware("http")(middles.black)
app.middleware("http")(middles.time_)
# app.middleware("http")(middles.black)
# app.middleware("http")(middles.time_)
# black_list = ['192.168.1.40','192.168.1.94'] # '127.0.0.1','192.168.1.26‘
# @app.middleware("http",)
# async def middleware(req:Request, next):
+44 -25
View File
@@ -1,5 +1,5 @@
from pydantic import BaseModel
from sqlalchemy.orm import declarative_base,sessionmaker
from sqlalchemy.orm import declarative_base,sessionmaker,Session
from sqlalchemy import Column, Integer,String,DATETIME,create_engine
from datetime import datetime
@@ -8,33 +8,56 @@ engine = create_engine(db_url)
def get_session():
Session = sessionmaker(bind=engine
, autoflush=False
, autocommit=False
)
yield Session()
# Session = sessionmaker(bind=engine
# , autoflush=False
# , autocommit=False
# )
# session = Session(engine)
# try:
# yield session
# finally:
# session.close()
with Session() as session:
yield session
# with Session(engine) as session:
# yield session
Base = declarative_base() # 执行函数,返回一个基类
class Order(Base): # python里的表名字
__tablename__ = 'order_info_detail' # 实际数据库的表名字
id = Column( Integer # 声明字段的数据类型
, primary_key=True # 声明是主键
, autoincrement=True # 声明是自增主键
, comment='订单编号,自增主键' # 注释
)
from model.template import Template
class Order(Base,Template): # python里的表名字
__tablename__ = 'order_info_bool_tinyint' # 实际数据库的表名字
title = Column( String(50) # 对应数据库的varchar类型
,nullable=False # 不允许为null
)
userid = Column( Integer
# ,ForeignKey('user_info_detail.id')
,nullable=False ) # 外键约束
create_date = Column(DATETIME
, default=datetime.now # 默认值是当前时间
)
update_date = Column(DATETIME
, default=datetime.now # 首次创建的时间跟更新时间一致
, onupdate=datetime.now
)
# class Order(Base): # python里的表名字
# __tablename__ = 'order_info_detail' # 实际数据库的表名字
# id = Column( Integer # 声明字段的数据类型
# , primary_key=True # 声明是主键
# , autoincrement=True # 声明是自增主键
# , comment='订单编号,自增主键' # 注释
# )
# title = Column( String(50) # 对应数据库的varchar类型
# ,nullable=False # 不允许为null
# )
# userid = Column( Integer
# # ,ForeignKey('user_info_detail.id')
# ,nullable=False ) # 外键约束
# create_date = Column(DATETIME
# , default=datetime.now # 默认值是当前时间
# )
# update_date = Column(DATETIME
# , default=datetime.now # 首次创建的时间跟更新时间一致
# , onupdate=datetime.now
# )
# 定义创建订单的请求体模型
class OrderRequest(BaseModel):
@@ -51,11 +74,7 @@ class OrderSchema(BaseModel):
update_date:datetime
class OrderResponse(BaseModel):
# id:int|None = None
# title:str|None = None
# userid:int|None =None
# create_date:datetime|None = datetime.now()
# update_date:datetime|None = datetime.now()
status_code:str = 200
detail:str = 'succeed!'
total:int = 1
+19
View File
@@ -0,0 +1,19 @@
from sqlalchemy import Column, Integer, String, DATETIME, create_engine, Boolean,Text,text
from datetime import datetime
# 定义基类模板,解决通用字段
class Template():
id = Column( Integer # 声明字段的数据类型
, primary_key=True # 声明是主键
, autoincrement=True # 声明是自增主键
, comment='订单编号,自增主键' # 注释
)
create_datetime = Column(DATETIME
, default=datetime.now # 默认值是当前时间
)
update_datetime = Column(DATETIME
, default=datetime.now # 首次创建的时间跟更新时间一致
, onupdate=datetime.now
)
is_deleted = Column(Boolean, default=False,server_default=text("0"))
delete_datetime = Column(DATETIME, nullable=True)
+2
View File
@@ -3,6 +3,8 @@ name = "fastapi-tutor"
version = "0.1.0"
requires-python = ">=3.13"
dependencies = [
"aiomysql>=0.3.2",
"asyncmy>=0.2.15",
"fastapi[standard]>=0.141.1",
"pymysql>=1.2.3",
"sqlalchemy>=2.0.54",
+2 -1
View File
@@ -9,11 +9,12 @@ from model.order import OrderRequest,Order,get_session,OrderResponse
from dao.order_dao import get_order
route = APIRouter(prefix="/order",tags=["orders"])
route = APIRouter(prefix="/order",tags=["order"])
# 模糊查询
@route.get('/',response_model=OrderResponse)
def orders(id:int=None, user_id:int=None, title:str=None,session=Depends(get_session)):
return get_order(id,user_id,title,session)
# todo 请求响应模型序列化Order类问题
+77
View File
@@ -0,0 +1,77 @@
# 编写更订单相关的增删改查接口,结合数据库
from fastapi import FastAPI, APIRouter, Depends
from sqlalchemy import *
from sqlalchemy.orm import declarative_base,sessionmaker
from datetime import datetime
from pydantic import BaseModel
from model.order import OrderRequest,Order,get_session,OrderResponse
from dao.order_dao import get_order
route = APIRouter(prefix="/order_select_query",tags=["order_select_query"])
# 模糊查询
@route.get('/query',response_model=OrderResponse)
def orders(id:int=None, user_id:int=None, title:str=None,session=Depends(get_session)):
q = session.query(Order)
if id: q = q.filter(Order.id == id)
if user_id: q = q.filter(Order.userid == user_id)
if title: q = q.where(Order.title.like('%' + title + '%'))
res = q.all()
return {"data": [{"order_id": r.id, 'order_title': r.title, "user_id": r.userid, "create_date": r.create_date,
"update_date": r.update_date} for r in res]}
@route.get('/select', response_model=OrderResponse)
def orders(id: int = None, user_id: int = None, title: str = None, session=Depends(get_session)):
s = select(Order)
if id: s = s.filter(Order.id == id)
if user_id: s = s.filter(Order.userid == user_id)
if title: s = s.where(Order.title.like('%' + title + '%'))
res = session.execute(s)
return {"data": [{"order_id": r.id, 'order_title': r.title, "user_id": r.userid, "create_date": r.create_date,
"update_date": r.update_date} for r in res]}
# todo 请求响应模型序列化Order类问题
@route.get('/no_response_model')
def orders(id:int=None, user_id:int=None, title:str=None,session=Depends(get_session)):
q = session.query(Order)
if id: q = q.filter(Order.id == id)
if user_id: q = q.filter(Order.userid == user_id)
if title: q = q.where(Order.title.like('%' + title + '%'))
res = q.all()
return res
@route.get('/{id}',response_model=OrderResponse)
def orders(id:int,session=Depends(get_session)):
r = session.query(Order).filter( Order.id == id ).first()
session.close()
return {"data":
{"order_id":r.id,'order_title':r.title,"user_id":r.userid,"create_date":r.create_date,"update_date":r.update_date}
}
@route.delete('/',response_model=OrderResponse)
def orders(session=Depends(get_session)):
return '删除订单'
@route.post('/',response_model=OrderResponse)
def orders(order:OrderRequest,session=Depends(get_session)):
d = order.model_dump() # d = {"title":xxx,"userid":xxx}
o1 = Order( **d )
session.add(o1)
session.commit()
session.close()
return {'code':200,'detail':'添加成功!'}
@route.put('/{id}',response_model=OrderResponse)
def orders(order:OrderRequest,id:int,session=Depends(get_session)):
r = session.query( Order ).filter( Order.id == id ).update( order.model_dump(exclude_unset=True) )
session.commit()
session.close()
return OrderResponse(status_code='200',detail='ok',total=r)
+28
View File
@@ -0,0 +1,28 @@
from sqlalchemy import Column, Integer
from sqlalchemy.ext.asyncio import create_async_engine, async_sessionmaker, AsyncSession
from sqlalchemy.orm import sessionmaker,declarative_base,DeclarativeBase
from fastapi import APIRouter, Depends
from debug.orm_app.sqlalchemy_full_app import User
route = APIRouter(prefix="/session",tags=["session"])
db_url = "mysql+aiomysql://geeker:geeker@localhost:3306/fastapi_tutor?charset=utf8mb4"
engine = create_async_engine(db_url)
async_session = async_sessionmaker(engine, expire_on_commit=False)
async def get_db() -> AsyncSession:
async with async_session() as session:
yield session
@route.get("/")
async def index(session: AsyncSession = Depends(get_db)):
u1 = User(username='test session')
session.add(u1)
await session.commit()
Generated
+728 -672
View File
File diff suppressed because it is too large Load Diff