使用 fastAPI 将嵌套模式插入数据库?
Insert a nested schema into a database with fastAPI?
我最近开始了解 fastAPI 并通过教程和其他文档进行了研究。尽管 fastAPI 有很好的文档记录,但我找不到有关在使用数据库时如何处理嵌套输入的信息。
为了测试,我写了一个非常小的 family API 有两个模型:
class Member(Base):
__tablename__ = 'members'
id = Column(Integer, primary_key=True, server_default=text("nextval('members_id_seq'::regclass)"))
name = Column(String(128), nullable=False)
age = Column(Integer, nullable=True)
family_id = Column(Integer, ForeignKey('families.id', deferrable=True, initially='DEFERRED'), nullable=False, index=True)
family = relationship("Family", back_populates="members")
class Family(Base):
__tablename__ = 'families'
id = Column(Integer, primary_key=True, server_default=text("nextval('families_id_seq'::regclass)"))
family_name = Column(String(128), nullable=False)
members = relationship("Member", back_populates="family")
我创建了一个包含两个表和此处描述的关系的 Postgres 数据库。使用 fastAPI 教程中的模式定义和 crud 文件,我可以创建单独的家庭和成员,并使用 get 请求以嵌套方式查看它们。这是嵌套架构:
class Family(FamilyBase):
id: int
members: List[Member]
class Config:
orm_mode = True
到目前为止,还不错。现在,我想添加一个 post 视图,它接受嵌套结构作为输入并相应地填充数据库。 https://fastapi.tiangolo.com/tutorial/body-nested-models/ 上的文档显示了原则上如何执行此操作,但它遗漏了数据库(即 crud)部分。
由于输入不会有 id
字段,显然不需要指定 family_id
,我有一个 MemberStub
模式和 NestedFamilyCreate
模式如下:
class MemberStub(BaseModel):
name: str
age: int
class NestedFamilyCreate(BaseModel):
family_name: str
members: List[MemberStub]
在我的路由例程中 families.py
我有:
@app.post('/nested-families/', response_model=schemas.Family)
def create_family(family: schemas.NestedFamilyCreate, db: Session = Depends(get_db)):
# no check for previous existence as names can be duplicates
return crud.create_nested_family(db=db, family=family)
(response_model 指向包含所有成员(包括所有 ID)的家庭的嵌套视图;见上文)。
我想不通的是如何编写 crud.create_nested_family
例程。基于教程中的简单创建,如下所示:
def create_nested_family(db: Session, family: schemas.NestedFamilyCreate):
# split information in family and members
members = family.members
core_family = None # ??? This is where I get stuck
db_family = models.Family(**family.dict()) # This fails
db.add(db_family)
db.commit()
db.refresh(db_family)
return db_family
因此,我可以提取成员并循环遍历它们,但我首先需要创建一个新的 db_family
记录,该记录不得包含成员。然后,使用 db.refresh
,我会得到新的 family_id,我可以将其添加到 members
的每条记录中。但是我该怎么做呢?如果我明白这里需要什么,我将需要将我的嵌套模式映射到 FamilyCreate 的普通模式(它自己工作)和 MemberCreate 的普通模式(它自己也工作)。但是我该怎么做呢?
在重新阅读 Pydantic 模型及其到 dict 的映射后,我找到了解决方案。
在crud.py中:
def create_nested_family(db: Session, family: schemas.NestedFamilyCreate):
# split information in family and members
family_data = family.dict()
member_data = family_data.pop('members', None) # ToDo: handle error if no members
db_family = models.Family(**family_data)
db.add(db_family)
db.commit()
db.refresh(db_family)
# get family_id
family_id = db_family.id
# add members
for m in member_data:
m['family_id'] = family_id
db_member = models.Member(**m)
db.add(db_member)
db.commit()
db.refresh(db_member)
return db_family
希望这对其他人有用。
我最近开始了解 fastAPI 并通过教程和其他文档进行了研究。尽管 fastAPI 有很好的文档记录,但我找不到有关在使用数据库时如何处理嵌套输入的信息。
为了测试,我写了一个非常小的 family API 有两个模型:
class Member(Base):
__tablename__ = 'members'
id = Column(Integer, primary_key=True, server_default=text("nextval('members_id_seq'::regclass)"))
name = Column(String(128), nullable=False)
age = Column(Integer, nullable=True)
family_id = Column(Integer, ForeignKey('families.id', deferrable=True, initially='DEFERRED'), nullable=False, index=True)
family = relationship("Family", back_populates="members")
class Family(Base):
__tablename__ = 'families'
id = Column(Integer, primary_key=True, server_default=text("nextval('families_id_seq'::regclass)"))
family_name = Column(String(128), nullable=False)
members = relationship("Member", back_populates="family")
我创建了一个包含两个表和此处描述的关系的 Postgres 数据库。使用 fastAPI 教程中的模式定义和 crud 文件,我可以创建单独的家庭和成员,并使用 get 请求以嵌套方式查看它们。这是嵌套架构:
class Family(FamilyBase):
id: int
members: List[Member]
class Config:
orm_mode = True
到目前为止,还不错。现在,我想添加一个 post 视图,它接受嵌套结构作为输入并相应地填充数据库。 https://fastapi.tiangolo.com/tutorial/body-nested-models/ 上的文档显示了原则上如何执行此操作,但它遗漏了数据库(即 crud)部分。
由于输入不会有 id
字段,显然不需要指定 family_id
,我有一个 MemberStub
模式和 NestedFamilyCreate
模式如下:
class MemberStub(BaseModel):
name: str
age: int
class NestedFamilyCreate(BaseModel):
family_name: str
members: List[MemberStub]
在我的路由例程中 families.py
我有:
@app.post('/nested-families/', response_model=schemas.Family)
def create_family(family: schemas.NestedFamilyCreate, db: Session = Depends(get_db)):
# no check for previous existence as names can be duplicates
return crud.create_nested_family(db=db, family=family)
(response_model 指向包含所有成员(包括所有 ID)的家庭的嵌套视图;见上文)。
我想不通的是如何编写 crud.create_nested_family
例程。基于教程中的简单创建,如下所示:
def create_nested_family(db: Session, family: schemas.NestedFamilyCreate):
# split information in family and members
members = family.members
core_family = None # ??? This is where I get stuck
db_family = models.Family(**family.dict()) # This fails
db.add(db_family)
db.commit()
db.refresh(db_family)
return db_family
因此,我可以提取成员并循环遍历它们,但我首先需要创建一个新的 db_family
记录,该记录不得包含成员。然后,使用 db.refresh
,我会得到新的 family_id,我可以将其添加到 members
的每条记录中。但是我该怎么做呢?如果我明白这里需要什么,我将需要将我的嵌套模式映射到 FamilyCreate 的普通模式(它自己工作)和 MemberCreate 的普通模式(它自己也工作)。但是我该怎么做呢?
在重新阅读 Pydantic 模型及其到 dict 的映射后,我找到了解决方案。
在crud.py中:
def create_nested_family(db: Session, family: schemas.NestedFamilyCreate):
# split information in family and members
family_data = family.dict()
member_data = family_data.pop('members', None) # ToDo: handle error if no members
db_family = models.Family(**family_data)
db.add(db_family)
db.commit()
db.refresh(db_family)
# get family_id
family_id = db_family.id
# add members
for m in member_data:
m['family_id'] = family_id
db_member = models.Member(**m)
db.add(db_member)
db.commit()
db.refresh(db_member)
return db_family
希望这对其他人有用。