Wil*_*aly 5 python marshmallow pydantic fastapi
是否可以dump_only
使用 FastAPI 的 pydantic 复制 Marshmallow 的功能,以便某些字段是“只读”,而不需要为序列化和反序列化定义单独的模式?
有时,给定 API 资源的属性子集(例如id
和created_date
)应该是只读的,并且应该在反序列化期间从请求有效负载中忽略(例如,当 POST 到集合或 PUT 到现有资源时),但需要对于这些相同的请求,将在响应正文中与该架构一起返回。
Marshmallow 提供了一个方便的dump_only
参数,只需要为序列化和反序列化定义一个模式,并可以选择从任一操作中排除某些字段。
我见过的在 FastAPI 中复制此功能的大多数尝试(即FastAPI 文档、GitHub 问题、相关 SO 问题)倾向于为输入(反序列化)和输出(序列化)定义单独的模式,并为之间的共享字段定义一个通用的基本模式。他们俩。
根据我目前对这种方法的理解,由于以下几个原因,它似乎有点不方便:
假设我们正在为具有以下模型的调查开发一个简单的 API:
from sqlalchemy.orm import declarative_base, relationship
from sqlalchemy import (
func,
Column,
Integer,
String,
DateTime,
ForeignKey,
)
Base = declarative_base()
class SurveyModel(db.Base):
"""Table that represents a collection of questions"""
__tablename__ = "survey"
# columns
id = Column(Integer, primary_key=True, index=True)
name = Column(String, nullable=False)
created_date = Column(DateTime, default=func.now())
# relationships
questions = relationship("Question", backref="survey")
class QuestionModel(Base):
"""Table that contains the questions that comprise a given survey"""
__tablename__ = "question"
# columns
id = Column(Integer, primary_key=True, index=True)
survey_id = Column(Integer, ForeignKey("survey.id"))
text = Column(String)
created_date = Column(DateTime, default=func.now())
Run Code Online (Sandbox Code Playgroud)
我们希望POST /surveys
端点能够接受请求正文中的以下有效负载:
{
"name": "First Survey",
"questions": [
{"text": "Question 1"},
{"text": "Question 2"}
]
}
Run Code Online (Sandbox Code Playgroud)
并在响应正文中返回以下内容:
{
"id": 1,
"name": "First Survey",
"created_date": "2021-12-12T00:00:30",
"questions": [
{
"id": 1,
"text": "Question 1",
"created_date": "2021-12-12T00:00:30"
},
{
"id": 2,
"text": "Question 2",
"created_date": "2021-12-12T00:00:30"
},
]
}
Run Code Online (Sandbox Code Playgroud)
除了像这样定义模式之外,还有其他方法可以使两者都id
成为created_date
只读模式吗?QuestionModel
SurveyModel
{
"name": "First Survey",
"questions": [
{"text": "Question 1"},
{"text": "Question 2"}
]
}
Run Code Online (Sandbox Code Playgroud)
为了进行比较,这里是使用棉花糖的等效模式:
from marshmallow import Schema, fields
class Question(Schema):
id = fields.Integer(dump_only=True)
created_date = fields.DateTime(dump_only=True)
text = fields.String(required=True)
class Survey(Schema):
id = fields.Integer(dump_only=True)
created_date = fields.DateTime(dump_only=True)
name = fields.String(required=True)
questions = fields.List(fields.Nested(Question))
Run Code Online (Sandbox Code Playgroud)
根据pydantic.Field
文档:
init_var
\xc2\xad\xe2\x80\x94 该字段是否应包含在数据类的构造函数中。exclude
\xe2\x80\x94 是否从模型序列化中排除该字段。因此,要从 Pydantic 中的方法处理的“反序列化”中排除某个字段,设置为BaseModel.__init__
就足够了。init_var
False
在 Pydantic 中重写示例将导致如下结果:
\nfrom datetime import datetime\n\nfrom Pydantic import BaseModel, Field\n\n\nclass Question(BaseModel):\n id: int = Field(init_var=False)\n created_date: datetime = Field(init_var=False)\n text: str\n\nclass Survey(BaseModel):\n id: int = Field(init_var=False)\n created_date: datetime = Field(init_var=False)\n name: str\n questions: list[Question]\n
Run Code Online (Sandbox Code Playgroud)\n
归档时间: |
|
查看次数: |
2899 次 |
最近记录: |