FastAPI结合Ormar使用ForwardRef时出现未定义错误求助
问题解决:Ormar多对多关系中的
PydanticUndefinedAnnotation错误 错误根源分析
你的代码存在两个关键问题:
- User类重复定义email字段:同一个模型里出现两次
email属性,会导致Pydantic解析模型时出错,同时干扰Ormar的ORM映射逻辑。 - ForwardRef处理不完整:虽然调用了
User.update_forward_refs(),但多对多关系需要双向定义,且需确保更新引用时上下文包含完整的模型定义。
修正后的代码
import uuid import datetime import sqlalchemy import databases import ormar from typing import ForwardRef # 假设config已正确导入 database = databases.Database(config.database_url) metadata = sqlalchemy.MetaData() base_ormar_config = ormar.OrmarConfig( metadata=metadata, database=database, ) ProjectRef = ForwardRef("Project") class BaseModel(ormar.Model): ormar_config = base_ormar_config.copy(abstract=True) id: str = ormar.UUID(primary_key=True, default=uuid.uuid4, uuid_format="string") created_at: datetime.datetime = ormar.DateTime(server_default=sqlalchemy.func.now()) class User(BaseModel): ormar_config = base_ormar_config.copy(tablename="users") subscription: str = ormar.String(max_length=254, nullable=True) # 保留唯一且非空的email字段,删除重复定义 email: str = ormar.String(max_length=244, nullable=False, unique=True) name: str = ormar.String(max_length=555, nullable=True) phone: str = ormar.String(max_length=555, nullable=True) company_name: str = ormar.String(max_length=555, nullable=True) occupation: str = ormar.String(max_length=555, nullable=True) # 多对多关系定义,使用ForwardRef projects = ormar.ManyToMany(ProjectRef) class Project(BaseModel): ormar_config = base_ormar_config.copy(tablename="projects") owner: User = ormar.ForeignKey(User, name="owner_id") name: str = ormar.String(max_length=244, nullable=True) description: str = ormar.String(max_length=555, nullable=True) files: list[str] = ormar.JSON(default=list) # 添加多对多的反向关系(可选,但推荐保持关系双向) users = ormar.ManyToMany(User, related_name="projects") # 同时更新两个模型的forward refs User.update_forward_refs() Project.update_forward_refs()
关键修改说明
- 删除重复的email字段:保留
nullable=False且unique=True的版本,符合用户邮箱唯一且必填的业务逻辑。 - 添加反向多对多关系:在Project类中定义
users = ormar.ManyToMany(User, related_name="projects"),确保关系双向可访问,帮助Ormar正确解析模型依赖。 - 更新两个模型的forward refs:除了User,也要调用
Project.update_forward_refs(),确保两个模型都能正确解析对方的引用。
替代简化方案(无需显式ForwardRef)
Ormar支持直接使用字符串形式的模型名称定义延迟引用,可省去显式创建ForwardRef的步骤,代码更简洁:
# 移除ProjectRef = ForwardRef("Project")这一行 class User(BaseModel): # ... 其他字段 projects = ormar.ManyToMany("Project") # 直接用字符串引用 class Project(BaseModel): # ... 其他字段 users = ormar.ManyToMany(User, related_name="projects") # 同样需要调用update_forward_refs User.update_forward_refs() Project.update_forward_refs()
内容的提问来源于stack exchange,提问作者Devon Ray
相关产品推荐
相关产品推荐

