【问题标题】:SQLAlchemy ORM Relationship stopped workingSQLAlchemy ORM 关系停止工作
【发布时间】:2021-09-18 09:13:23
【问题描述】:

我使用 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()

ma​​in.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)

【问题讨论】:

    标签: python sqlalchemy fastapi pydantic


    【解决方案1】:

    在 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')
    

    【讨论】:

      猜你喜欢
      • 2015-04-29
      • 1970-01-01
      • 1970-01-01
      • 2018-10-04
      • 2020-05-16
      • 2021-06-26
      • 1970-01-01
      • 2016-08-17
      • 2014-10-13
      相关资源
      最近更新 更多