将嵌套子级sqlalchemy过滤到任意深度

时间:2019-04-02 22:35:21

标签: python flask sqlalchemy

我有一个复杂的模型。假设它包含100个实体,所有实体都以某种方式相互关联。有些是多对多的,有些是一对一的,有些是多对一的,依此类推。

这些实体都具有startend时间戳,指示有效时间范围。通过查询加载这些实体时,我希望仅使用具有startend标记并包裹给定时间戳记的实体来填充关系字段:例如datetime.now()或昨天,或在任何时候。

例如,我将在此处定义两个模型,但假设有很多其他模型:

class User(base):
    __tablename__ = 'User'

class Role(base):
    __tablename__ = 'Role'

    user_id = Column(Integer, ForeignKey('User.uid'))
    user = relationship(User, backref=backref('Role')
    start = Column(DateTime, default=func.current_timestamp())
    end = Column(DateTime))

现在,我想通过flask中的宁静端点返回实体。因此,get在烧瓶中可能看起来像这样:

def get(self, uid=None) -> Tuple[Dict, int]:
    query = User.query
    if uid:
        query.filter_by(uid=uid)
    return create_response(
        query.all()
        200
    )

现在,我想将作为子级返回的Role实体限制为上述查询返回的User。显然,只要扩展query来过滤角色,就可以轻松实现。当规模扩大时,问题就来了。考虑100个嵌套的子级关系。现在考虑为每个端点提供get的静态端点。几乎不可能写出query来正确过滤每个不同级别的孩子。

我想要的解决方案是在每个实体上定义加载行为,使所有内容都可组合。例如:

class User(base):
    __tablename__ = 'User'

    role = relationship("Role",
                     primaryjoin="and_(Role.start<={desired_timestamp} "
                                 "Role.end>={desired_timestamp})")

当然,问题在于我们在类定义时不知道我们的desired_timestamp,因为它是在运行时传递的。我想到了一些技巧,例如在每个运行时重新定义所有内容,但我对它们不满意。是否有人对做这样的事情的“正确”方法有所了解?

0 个答案:

没有答案