【发布时间】:2021-08-11 00:19:38
【问题描述】:
我是使用 SqlAlchemy 的新手,现在我使用的是 fastAPI,基本上我需要创建一个可以有多个嵌套参数的指标模型
这是我的代码
class Indicator(Base):
__tablename__ = "indicator"
id = Column(Integer, primary_key=True, autoincrement=True, index=True)
name = Column(String, unique=True, nullable=False)
indicator_lib_name = Column(String, unique=True, nullable=False)
properties = relationship("Property", backref="indicator", lazy=True,cascade="all, delete")
class Property(Base):
__tablename__ = "property"
id = Column(Integer, primary_key=True, autoincrement=True, index=True)
name = Column(String, unique=True, nullable=False)
value = Column(sqlalchemy_utils.ScalarListType, nullable=True)
indicator_id = Column(Integer, ForeignKey("indicator.id", ondelete="CASCADE"))
# indicator = relationship("Indicator", back_populates="properties")
from pydantic import BaseModel
class Property(BaseModel):
id: Optional[int]
name: str
value: List[Any]
class IndicatorCreate(BaseModel):
name: str
indicator_lib_name: Optional[str]
properties: List[Property]
# https://stackoverflow.com/questions/61144192/insert-a-nested-schema-into-a-database-with-fastapi
# https://dev.to/brandonwallace/one-to-many-relationships-complete-how-to-2nbi
def create_new_indicator(db: Session, indicator: IndicatorCreate):
indicator_data = indicator.dict()
properties = []
if indicator.properties:
properties = indicator_data.pop("properties", None)
new_indicator = Indicator(**indicator_data)
new_indicator.indicator_lib_name = indicator.indicator_lib_name or indicator.name
db.add(new_indicator)
db.commit()
db.refresh(new_indicator)
for prpty in properties:
# prpty["indicator"] = new_indicator
property_model = Property(**prpty, indicator=new_indicator)
db.add(property_model)
db.commit()
db.refresh(property_model)
db.refresh(new_indicator)
return new_indicator
@indicators_router.post("/", response_model=IndicatorBase)
def create_indicator(indicator: IndicatorCreate, db: Session = Depends(get_db)):
indicator_new = create_new_indicator(db, indicator)
print("indicator ", indicator_new)
return indicator_new
data = {
"name": "adx",
"indicator_name": "adx",
"properties": [{"name": "range", "value": [2]}],
}
def test_create_indicator(client):
global data
response = client.post("/indicators/", json.dumps(data))
data = response.json()
print(data)
assert response.status_code == 200
assert data["name"] == "adx"
assert data["id"] == 1
assert len(data["properties"]) == 1
错误是
> raise ValidationError(errors, field.type_)
E pydantic.error_wrappers.ValidationError: 1 validation error for IndicatorBase
E response -> properties -> 0
E value is not a valid dict (type=type_error.dict)
当我调试代码时,我可以看到属性填充正确,它得到的数据很好,但结构是 InstrumentedList 而不是 List,为什么?如何将其转换为列表或更好的问题:实现此目标的更好方法是什么?
我创建指标和参数的方式更好吗?还是有更简洁的方法?
非常感谢你们,希望你们能帮助我迈出 SQLAlchemy 的第一步
【问题讨论】:
-
如果您想了解有关 InstrumentedList 的更多信息:stackoverflow.com/questions/6654613/…
-
您的定义中没有包含
IndicatorBase;但属性未定义为可从 ORM 加载(即使用.foo而不是['foo']。您可以通过在架构类中添加class Config: orm_mode = True来更改它;这就是为什么 pydantic 类需要一个 dict:fastapi.tiangolo.com/tutorial/sql-databases/… -
@MatsLindh 成功了!谢谢,我为 IndicatorBase 添加了
orm_mode = true,但没有为 Property 添加,这就是问题所在,您能否包含您的答案以便接受它为有效的?
标签: python sqlalchemy fastapi