【问题标题】:How to model most recent version as default version in SQLAlchemy?如何将最新版本建模为 SQLAlchemy 中的默认版本?
【发布时间】:2023-02-25 19:54:07
【问题描述】:

假设您有这些(Flask)SQLAlchemy 模型,它们模拟一个帖子和几个不同版本的帖子,代表不同的时间点。这是帖子和版本之间的一对多关系。帖子的每个版本都有不同的点赞数,但您希望将最新版本视为默认版本,这样如果您尝试进行引用 Post.likes 的查询,您实际上是在加入版本表并查询喜欢来自版本表。

class Post(db.Model):
     __tablename__ = 'posts'
     post_id = Column(BigInteger, primary_key = True)
     
     versions = relationship('PostVersion', back_populates = 'post')


class PostVersion(db.Model):
     __tablename__ = 'post_versions'
     post_version_id = Column(BigInteger, primary_key = True)
     post_id = Column(ForeignKey(Post.post_id), primary_key = True)
     likes = Column(BigInteger)

     post = relationship('Post', back_populates = 'versions')

我们可以向这些模型中的任何一个添加什么样的混合属性表达式或其他方法来使以下查询(或接近它的东西)成为可能,而不仅仅是 likes 字段,而是任何字段?

posts = Post.query.filter(Post.likes >= 100).all()

或者

posts = Post.query.filter(Post.most_recent_version.likes > 100).all()

【问题讨论】:

    标签: python sqlalchemy model flask-sqlalchemy


    【解决方案1】:

    你可以试试这个sn-p。

    from sqlalchemy.ext.hybrid import hybrid_property
    
    
    class Post(base):
        __tablename__ = 'posts'
        post_id = Column(BigInteger, primary_key=True)
        versions = relationship('PostVersion', back_populates='post')
    
        @hybrid_property
        def likes(self):
            return self.versions[-1].likes
    

    我认为这应该有效。或者我可能会错过一些我没有正确理解问题的东西。

    【讨论】:

    • 如果您在下面为 likes 添加了混合属性表达式,那么这将允许您在查询中引用 likes。但我正在寻找可以推广到最新版本的任何领域的东西,而不必在 Post 模型上明确定义它。我刚刚更新了我的问题以更好地反映这一点。
    【解决方案2】:

    这是迄今为止我想到的最佳答案。尽管我仍然希望按照我在问题中指定的方式进行操作,但这可能是不可能的。

    class Post(db.Model):
         __tablename__ = 'posts'
         post_id = Column(BigInteger, primary_key = True)
    
         versions = relationship('PostVersion', back_populates = 'post')
    
         @hybrid_property
         def most_recent_version(self):
             return self.versions[-1]
    
    
    class PostVersion(db.Model):
         __tablename__ = 'post_versions'
         post_version_id = Column(BigInteger, primary_key = True)
         post_id = Column(ForeignKey(Post.post_id), primary_key = True)
         likes = Column(BigInteger)
    
         post = relationship('Post', back_populates = 'versions')
    
    
         @hybrid_property
         def is_most_recent_version(self):
             return self.version_id == self.post.most_recent_version.version_id
    
         @is_most_recent_version.expression
         def is_most_recent_version(cls):
            max_id_per_post = db.session.query(func.max(PostVersion.version_id)).group_by(PostVersion.version_id).subquery()
            return cls.version_id.in_(max_id_per_post)
    
    
    

    这让您可以运行此查询:

    mr_posts = Post.query.filter(PostVersion.is_most_recent_version)
    posts = mr_posts.filter(PostVersion.likes > 1).all()
    
    

    【讨论】:

      猜你喜欢
      • 2019-03-10
      • 1970-01-01
      • 2017-08-05
      • 1970-01-01
      • 1970-01-01
      • 2016-01-25
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多