SqlAlchemy contains_eager 不显示加载嵌套关系

2024-09-30 22:25:57 发布

您现在位置:Python中文网/ 问答频道 /正文

我有一个模式如下:

Thing # Base class for below tables
- id

Ball (Thing)
- color

Bin (Thing)
- ball -> Ball.id

Court (Thing)
- homeBin -> Bin.id
- awayBin -> Bin.id

我想确保每当我加载一组Court时,它都包含最新的Ball列值。据我所知,contains_eager()也许能帮上忙:

Indicate that the given attribute should be eagerly loaded from columns stated manually in the query.

我有一个测试,每隔几秒钟查询一次Court的值。我发现,即使使用contains_eager,我也只能看到Ball.color的相同值,即使我在数据库中显式更新了列的值。你知道吗

为什么sqlalchemy看起来会重用这些旧数据?你知道吗

下面是一个工作实例:

from sqlalchemy import *
from sqlalchemy.orm import *
from sqlalchemy.ext.associationproxy import association_proxy
from sqlalchemy.ext.declarative import declarative_base

Base = declarative_base()

class Thing(Base):
    __tablename__ = "Things"
    id = Column(Integer, primary_key=True)
    name = Column(String(256))
    thingType = Column(String(256))
    __mapper_args__ = {
            'with_polymorphic':'*',
            'polymorphic_on':"thingType",
            'polymorphic_identity':"thing"
        }


class Ball(Thing):
    __tablename__ = "Balls"
    id = Column('id', Integer, ForeignKey('Things.id'), primary_key=True)
    color = Column('color', String(256))
    __mapper_args__ = {
        'polymorphic_identity':'ball'
    }

class Bin(Thing):
    __tablename__ = "Bins"
    id = Column('id', Integer, ForeignKey('Things.id'), primary_key=True)
    shape = Column('shape', String(256))
    ballId = Column('ballId', Integer, ForeignKey('Balls.id'))
    ball = relationship(Ball, foreign_keys=[ballId], backref="outputBins")
    __mapper_args__ = {
        'polymorphic_identity':'bin'
    }
    pass

class Court(Thing):
    __tablename__ = "Courts"
    id = Column('id', Integer, ForeignKey('Things.id'), primary_key=True)
    homeBinId = Column('homeBinId', Integer, ForeignKey('Bins.id'))
    awayBinId = Column('awayBinId', Integer, ForeignKey('Bins.id'))
    homeBin = relationship(Bin, foreign_keys=[homeBinId], backref="homeCourts")
    awayBin = relationship(Bin, foreign_keys=[awayBinId], backref="awayCourts")
    __mapper_args__ = {
        'polymorphic_identity':'court'
    }

metadata = MetaData()
engine = create_engine("postgresql://localhost:5432/")
Session = sessionmaker(bind=engine)
session = Session()

def courtQuery():
    awayBalls = aliased(Ball, name="awayBalls")
    homeBalls = aliased(Ball, name="homeBalls")
    awayBins = aliased(Bin, name="awayBins")
    homeBins = aliased(Bin, name="homeBins")

    query = session.query(Court)\
        .outerjoin(awayBins, Court.awayBinId == awayBins.id)\
        .outerjoin(awayBalls, awayBins.ballId == awayBalls.id)\
        .outerjoin(homeBins, Court.homeBinId == homeBins.id)\
        .outerjoin(homeBalls, homeBins.ballId == homeBalls.id)\
        .options(contains_eager(Court.awayBin, alias=awayBins).contains_eager(awayBins.ball, alias=awayBalls))\
        .options(contains_eager(Court.homeBin, alias=homeBins).contains_eager(homeBins.ball, alias=homeBalls))
    return [r for r in query]

import time

while(True):
    results = courtQuery()
    court = results[0]
    ball = court.homeBin.ball
    print(ball.color) # does not change
    time.sleep(2)

环境:

  • Python 2.7.14版
  • SqlAlchemy 1.3.0b1版
  • PostGres 11.3(虽然我见过这个 在甲骨文上也是如此)

Tags: idbincolumnintegerclassthingcontainsforeignkey