SQLAlchemy ORM 关系停止工作
SQLAlchemy ORM Relationship stopped working
我使用 FastAPI、sqlalchemy 和 pydantic 构建了一个 API。 ORM 建模在一段时间内运行良好,但我更新了代码并以某种方式破坏了关系映射。请帮助我弄清楚我在 ORM 映射中做错了什么。
当我访问 http://localhost:8000/test-rel 时,我希望看到这个:
[{"name":"P One","pk_id":1,"fk_id":1, "test":{"test_id":1, "test_name":"One"}},{"name":"P Two","pk_id":2,"fk_id":2, "test":{"test_id":2, "test_name":"Two"}},{"name":"P Three","pk_id":3,"fk_id":null, "test": null}]
但我看到的是:
[{"name":"P One","pk_id":1,"fk_id":1},{"name":"P Two","pk_id":2,"fk_id":2},{"name":"P Three","pk_id":3,"fk_id":null}]
这是我用来排除故障的项目的测试代码部分:
schemas.py
from typing import Optional
from pydantic import BaseModel
class Test(BaseModel):
test_id: int
test_name: str
class TestP(BaseModel):
pk_id: int
fk_id: Optional[int]
name: Optional[str]
test: Test
class Config:
orm_mode = True
models.py
from sqlalchemy import Boolean, Column, ForeignKey, Integer, String, DATE, DECIMAL
from sqlalchemy.orm import relationship
from sql_app.database import Base
class Test(Base):
__tablename__ = "test"
test_id = Column(Integer, primary_key=True)
test_name = Column(String)
class TestP(Base):
__tablename__ = "test_p"
pk_id = Column(Integer, primary_key=True)
fk_id = Column(Integer, ForeignKey("test.test_id"), nullable=True)
name = Column(String, nullable=True)
test = relationship("Test")
database.py
from sqlalchemy import create_engine
from sqlalchemy.ext.declarative import declarative_base
from sqlalchemy.orm import sessionmaker
import urllib
params = urllib.parse.quote_plus("DRIVER={SQL Server Native Client 11.0};"
"SERVER=SQLEXPRESS;"
"DATABASE=Test;"
"Trusted_Connection=yes")
engine = create_engine(
"mssql+pyodbc:///?odbc_connect={}".format(params)
)
SessionLocal = sessionmaker(autocommit=False, autoflush=False, bind=engine)
Base = declarative_base()
crud.py
from sqlalchemy.orm import Session
from sqlalchemy import and_, update, delete
from fastapi.encoders import jsonable_encoder
from typing import List
from sql_app import models
from sql_app import schemas
def test_rel(db: Session) -> List[schemas.TestP]:
return db.query(models.TestP).all()
main.py
import babel.numbers as bn
from fastapi import Depends, FastAPI, HTTPException, Request
from fastapi.middleware.cors import CORSMiddleware
from sqlalchemy.orm import Session
from sql_app import crud, models, schemas
from sql_app.database import SessionLocal, engine
models.Base.metadata.create_all(bind=engine)
app = FastAPI()
def get_db():
db = SessionLocal()
try:
yield db
finally:
db.close()
@app.get("/test-rel/")
def test_rel(db: Session = Depends(get_db)):
return crud.test_rel(db=db)
在 CaseIIT 的 github 讨论中回答:
几件事:
def test_rel(db: Session) -> List[schemas.TestP]:
return db.query(models.TestP).all()
This returns a List[model.TestP]
默认情况下,关系也是延迟加载的。查看 https://docs.sqlalchemy.org/en/14/orm/loading_relationships.html 以获得预加载选项
我的回复:
这正是我要找的。我不知道默认情况下关系是延迟加载的。我的代码使用 pydantic 来验证响应,而我的查询验证失败,因为 pydantic 验证没有看到连接的表。我更新了我的代码以添加预先加载,它现在完全按照我的预期工作。
test = relationship("Test", lazy='joined')
我使用 FastAPI、sqlalchemy 和 pydantic 构建了一个 API。 ORM 建模在一段时间内运行良好,但我更新了代码并以某种方式破坏了关系映射。请帮助我弄清楚我在 ORM 映射中做错了什么。
当我访问 http://localhost:8000/test-rel 时,我希望看到这个:
[{"name":"P One","pk_id":1,"fk_id":1, "test":{"test_id":1, "test_name":"One"}},{"name":"P Two","pk_id":2,"fk_id":2, "test":{"test_id":2, "test_name":"Two"}},{"name":"P Three","pk_id":3,"fk_id":null, "test": null}]
但我看到的是:
[{"name":"P One","pk_id":1,"fk_id":1},{"name":"P Two","pk_id":2,"fk_id":2},{"name":"P Three","pk_id":3,"fk_id":null}]
这是我用来排除故障的项目的测试代码部分:
schemas.py
from typing import Optional
from pydantic import BaseModel
class Test(BaseModel):
test_id: int
test_name: str
class TestP(BaseModel):
pk_id: int
fk_id: Optional[int]
name: Optional[str]
test: Test
class Config:
orm_mode = True
models.py
from sqlalchemy import Boolean, Column, ForeignKey, Integer, String, DATE, DECIMAL
from sqlalchemy.orm import relationship
from sql_app.database import Base
class Test(Base):
__tablename__ = "test"
test_id = Column(Integer, primary_key=True)
test_name = Column(String)
class TestP(Base):
__tablename__ = "test_p"
pk_id = Column(Integer, primary_key=True)
fk_id = Column(Integer, ForeignKey("test.test_id"), nullable=True)
name = Column(String, nullable=True)
test = relationship("Test")
database.py
from sqlalchemy import create_engine
from sqlalchemy.ext.declarative import declarative_base
from sqlalchemy.orm import sessionmaker
import urllib
params = urllib.parse.quote_plus("DRIVER={SQL Server Native Client 11.0};"
"SERVER=SQLEXPRESS;"
"DATABASE=Test;"
"Trusted_Connection=yes")
engine = create_engine(
"mssql+pyodbc:///?odbc_connect={}".format(params)
)
SessionLocal = sessionmaker(autocommit=False, autoflush=False, bind=engine)
Base = declarative_base()
crud.py
from sqlalchemy.orm import Session
from sqlalchemy import and_, update, delete
from fastapi.encoders import jsonable_encoder
from typing import List
from sql_app import models
from sql_app import schemas
def test_rel(db: Session) -> List[schemas.TestP]:
return db.query(models.TestP).all()
main.py
import babel.numbers as bn
from fastapi import Depends, FastAPI, HTTPException, Request
from fastapi.middleware.cors import CORSMiddleware
from sqlalchemy.orm import Session
from sql_app import crud, models, schemas
from sql_app.database import SessionLocal, engine
models.Base.metadata.create_all(bind=engine)
app = FastAPI()
def get_db():
db = SessionLocal()
try:
yield db
finally:
db.close()
@app.get("/test-rel/")
def test_rel(db: Session = Depends(get_db)):
return crud.test_rel(db=db)
在 CaseIIT 的 github 讨论中回答:
几件事:
def test_rel(db: Session) -> List[schemas.TestP]:
return db.query(models.TestP).all()
This returns a List[model.TestP]
默认情况下,关系也是延迟加载的。查看 https://docs.sqlalchemy.org/en/14/orm/loading_relationships.html 以获得预加载选项
我的回复: 这正是我要找的。我不知道默认情况下关系是延迟加载的。我的代码使用 pydantic 来验证响应,而我的查询验证失败,因为 pydantic 验证没有看到连接的表。我更新了我的代码以添加预先加载,它现在完全按照我的预期工作。
test = relationship("Test", lazy='joined')