Playhouse(Peewee扩展)Signals异常:post_save的created参数恒为False
问题原因分析
你的问题出在User模型的UUID主键生成时机和Peewee信号中created参数的判定逻辑上:
- User模型的
id字段设置了default=uuid4,导致实例化User()时就自动生成了主键值 - Peewee的
post_save信号中,created参数的判定依据是实例是否有未保存的主键——因为你的User实例在保存前已经有了主键,即使执行的是INSERT操作,信号仍会认为这是更新操作,所以created始终为False
解决方案
提供三种可行方案,按需选择:
方案1:调整主键生成时机(推荐)
修改User模型的主键定义,让数据库在插入时自动生成UUID(以PostgreSQL为例,其他数据库可适配对应语法),这样实例化时主键为None,保存后Peewee会正确识别为新创建的记录:
import uuid from peewee import UUIDField, SQL class User(BaseModel): id = UUIDField(primary_key=True, default=None, constraints=[SQL('DEFAULT uuid_generate_v4()')]) tg_id = BigIntegerField(unique=True, null=True)
注意:PostgreSQL需要先启用uuid-ossp扩展(执行CREATE EXTENSION IF NOT EXISTS "uuid-ossp";)。如果是SQLite,可改用AutoField作为主键,或者在保存前手动生成UUID并赋值。
方案2:绕过信号的created参数判断
直接在信号中检查是否存在对应的UserSettings记录,不存在则创建,彻底摆脱对created参数的依赖:
@post_save(sender=User) def on_user_created(model_class: User, instance: User, created: bool): print("works1") # 直接获取或创建UserSettings,自动处理缺失情况 UserSettings.get_or_create(user=instance)
这种方法更健壮,即使后续业务逻辑变更导致保存方式改变,也能保证UserSettings始终存在。
方案3:在用户创建逻辑中手动关联
如果不想依赖信号,可以在create_or_update_user_tg函数中,当确认是创建新用户时直接生成UserSettings:
def create_or_update_user_tg(tg_id: int, name: str, age: int, city: str, gender: Gender, search_gender: SearchGender, profile_description: str = None, location: Location = None, medias: typing.List[tuple[str]] = None) -> \ typing.Union[User, None]: u, is_creating = User.get_or_none(tg_id=tg_id), False if not u: u, is_creating = User(), True u.tg_id = tg_id u.name = name u.age = age u.city = city u.gender = gender.value u.search_gender = search_gender.value u.profile_description = profile_description if location: u.longitude = location.longitude u.latitude = location.latitude u.save(force_insert=is_creating) # 新增:创建UserSettings(仅当新用户时) if is_creating: UserSettings.create(user=u) upload_user_medias(u.tg_id, medias, delete_existing=True) return u
内容的提问来源于stack exchange,提问作者Bekhruz
相关产品推荐
相关产品推荐

