使用 Pydantic 创建 CSV 行
use Pydantic to create CSV line
我们使用 Pydantic 来设置“领域模型”并在整个应用层使用它们。
import datetime
from decimal import Decimal
from pydantic import BaseModel
class Person(BaseModel):
name: str
birth_date: datetime.date
height: Decimal
# other 100 fields, most of them Decimal
现在我们需要将其中一个模型导出为 CSV,第一个实现很简单:
import csv
from typing import Iterable
def store(persons: Iterable[Person]):
fieldnames = list(Person.schema()["properties"].keys())
with open("/tmp/test.csv", "w") as fp:
writer = csv.DictWriter(fp, fieldnames=fieldnames)
writer.writeheader()
for person in persons:
writer.writerow(person.dict())
但是还有更多,因为我们希望所有的小数都限制在小数点后两位,如何实现呢?
注意:不会将序列化逻辑放在域模型中,但我愿意为序列化创建一个新模型。
您可以使用自定义 json 编码器来舍入模型中的所有小数(不幸的是,在 json_encoders
中使用 Decimal
作为结果类型是行不通的,因为它不是JSON 可序列化。
我还定义了一个继承自 Person
的模型 PersonOut
,因此您不必将序列化逻辑存储在域模型中。在行编写器中,模型映射到序列化模型。
import csv
import json
from decimal import Decimal
from pydantic import BaseModel
from typing import Iterable
class Person(BaseModel):
""" Person domain model. """
name: str
height: Decimal
class PersonOut(Person):
""" Person model used for serialization. """
class Config:
json_encoders = { Decimal: lambda v: float(round(v, 2)) }
def store(persons: Iterable[Person]):
fieldnames = list(Person.schema()["properties"].keys())
with open("test.csv", "w") as fp:
writer = csv.DictWriter(fp, fieldnames=fieldnames)
writer.writeheader()
for person in persons:
writer.writerow(json.loads(PersonOut(**person.dict()).json()))
if __name__=="__main__":
persons = [Person(name='test', height=1.743)]
store(persons)
我们使用 Pydantic 来设置“领域模型”并在整个应用层使用它们。
import datetime
from decimal import Decimal
from pydantic import BaseModel
class Person(BaseModel):
name: str
birth_date: datetime.date
height: Decimal
# other 100 fields, most of them Decimal
现在我们需要将其中一个模型导出为 CSV,第一个实现很简单:
import csv
from typing import Iterable
def store(persons: Iterable[Person]):
fieldnames = list(Person.schema()["properties"].keys())
with open("/tmp/test.csv", "w") as fp:
writer = csv.DictWriter(fp, fieldnames=fieldnames)
writer.writeheader()
for person in persons:
writer.writerow(person.dict())
但是还有更多,因为我们希望所有的小数都限制在小数点后两位,如何实现呢?
注意:不会将序列化逻辑放在域模型中,但我愿意为序列化创建一个新模型。
您可以使用自定义 json 编码器来舍入模型中的所有小数(不幸的是,在 json_encoders
中使用 Decimal
作为结果类型是行不通的,因为它不是JSON 可序列化。
我还定义了一个继承自 Person
的模型 PersonOut
,因此您不必将序列化逻辑存储在域模型中。在行编写器中,模型映射到序列化模型。
import csv
import json
from decimal import Decimal
from pydantic import BaseModel
from typing import Iterable
class Person(BaseModel):
""" Person domain model. """
name: str
height: Decimal
class PersonOut(Person):
""" Person model used for serialization. """
class Config:
json_encoders = { Decimal: lambda v: float(round(v, 2)) }
def store(persons: Iterable[Person]):
fieldnames = list(Person.schema()["properties"].keys())
with open("test.csv", "w") as fp:
writer = csv.DictWriter(fp, fieldnames=fieldnames)
writer.writeheader()
for person in persons:
writer.writerow(json.loads(PersonOut(**person.dict()).json()))
if __name__=="__main__":
persons = [Person(name='test', height=1.743)]
store(persons)