【问题标题】:Shorthand for querying a table in Flask-SQLAlchemy在 Flask-SQLAlchemy 中查询表的简写
【发布时间】:2017-07-27 07:18:24
【问题描述】:

假设我有一个名为 User 的模型和一个名为 followers 的表格:

followers = db.Table(
    'followers',
    db.Column('follower_id', db.Integer, db.ForeignKey('user.id')),
    db.Column('followed_id', db.Integer, db.ForeignKey('user.id'))
)

class User(db.Model):
    id = db.Column(db.Integer, primary_key=True)
    username = db.Column(db.String(64), index=True, unique=True)
    followed = db.relationship(
        'User',
        secondary=followers,
        primaryjoin=(followers.c.follower_id==id),
        secondaryjoin=(followers.c.followed_id==id),
        backref=db.backref('followers', lazy='dynamic'),
        lazy='dynamic'
    )

查询User模型有两种方式:

  1. db.session.query(User).filter(...).all()
  2. User.query.filter(...).all()

后者被认为是前者的简写,因为它们在功能上相同但更紧凑。但是,当谈到桌子时,followers.query.filter(...).all() 给了我一个错误:

AttributeError: 'Table' 对象没有属性 'query'

db.session.query(followers).filter(...).all() 有简写吗?或者,如何从table 对象中获取query 对象?

【问题讨论】:

    标签: orm sqlalchemy flask-sqlalchemy


    【解决方案1】:

    flask-sqlalchemy 仅在 db.Model 上定义 query,因此虽然您可以在任何子类 db.Model 上执行 Foo.query,但您不能在 Table 实例上执行相同操作。

    我想你可以将它添加进去,但我不建议这样做。

    【讨论】:

      【解决方案2】:

      添加到@univerio 答案:您可以将flask_sqlalchemy.Table 包装到您的自定义类中,而不是猴子补丁,其中将包含query 属性作为简写。

      class QueryableTable:
      
          def __init__(self, *args, **kwargs):
              table = db.Table(*args, **kwargs)
              super().__setattr__('_flask_sa_table', table)
      
          @property
          def query(self):
              return db.session.query(self._flask_sa_table)
      
          def __getattr__(self, name):
              return getattr(self.__dict__['_flask_sa_table'], name)
      
          def __setattr__(self, name, value):
              return setattr(self._flask_sa_table, name, value)
      

      将其用作followers = QueryableTable('followers', db.Column(...), ...)

      【讨论】:

        【解决方案3】:

        您的 Follower 对象可能有问题,您可能想再次检查一下。

        Follower.query.all() 应该可以工作

        如果您碰巧在您的用户中与诸如此类的追随者有关系。

        class User():
            followers = db.relationship("Followers", lazy='dynamic')
        

        您可以通过以下方式执行:

        user = User.query.get(id=1)
        user.followers.all()
        

        *更新

        followers 表的声明不等同于您声明 User 表的方式。用户表基于 db.Model 并且 db.Model 附加了一个查询类: http://flask-sqlalchemy.pocoo.org/2.1/api/#flask.ext.sqlalchemy.Model

        您也可以查看页面底部的启蒙之路部分。

        http://flask-sqlalchemy.pocoo.org/2.1/quickstart/#quickstart

        【讨论】:

        • 在我的问题中,followers 不是模型User 的字段,它是一个单独的
        • 请发布您的关注者和用户架构或表定义
        • 已发布定义。
        • 好的,发布后它与您声明关注者表的方式有关。我已经为你更新了答案。 Followers 表不是 db.Model 的类,这就是您无法执行查询类的原因。
        【解决方案4】:

        要使用session.query() 方法从表中检索行,您必须将表名放在query() 中。

        例如:表名“fellowers”,输入session.query(fellowers).filter_by(id = fellow_id).one()

        【讨论】:

        • 是的,没错,但我的问题是关于session.query(fellowers).filter_by(id = fellow_id).one()简写
        【解决方案5】:

        我不确定我使用的解决方案有多传统,但我采用了pandas.read_sql_query (link),所以它或多或少是这样工作的:

        pandas.read_sql_query('SELECT your_table_column from followers WHERE follower_id = your_id', your_app.config['SQLALCHEMY_DATABASE_URI'])
        

        这为我提供了与所需 follower_id 相关的所有记录作为 pandas 数据框,可以进一步处理。

        【讨论】:

          猜你喜欢
          • 2013-07-24
          • 2013-05-10
          • 2015-03-10
          • 1970-01-01
          • 2022-01-07
          • 2019-04-23
          • 2019-12-13
          • 2017-08-28
          • 1970-01-01
          相关资源
          最近更新 更多