python - 如何使用多级/多连接在 SQLAlchemy 中指定表关系?

标签 python sqlalchemy flask flask-sqlalchemy

我正在尝试定义两个间接关系(即通过其他两个表)的表之间的关系。

我正在寻找的结果可以通过这个查询获取:

(db.session.query(Telnum)
           .filter(Account.customer==customer)
           .filter(Account.account_id == Subscription.account_id)
           .filter(Telnum.sub_id == Subscription.id)
           .order_by(Telnum.telnum)
           .all()
)

其中 customer 是一个 Customer 对象。

我正在努力弄清楚如何将其定义为一种关系,类似于 Customer.invoices 关系。我的想法是这样的:

telnums = db.relationship('Telnum',
                       primaryjoin="and_(Account.user_id==Customer.id, "
                       "Account.account_id == Subscription.account_id, " 
                       "Telnum.sub_id == Subscription.id)", 
                       backref='customer')

正如这篇文章所表明的那样,这是行不通的。它产生的错误信息是这样的: sqlalchemy.exc.ArgumentError:无法找到任何简单的相等表达式,涉及主要连接条件的本地映射外键列 'accounts.user_id = customers.id AND accounts.account_id = subscriptions.account_id AND pstn_numbers.sub_id = subscriptions.id ' 在关系 Customer.telnums 上。确保引用列与 ForeignKey 或 ForeignKeyConstraint 相关联,或者在连接条件中使用 foreign() 注释进行注释。要允许“==”以外的比较运算符,可以将关系标记为 viewonly=True。

谁能给我指明正确的方向?

我有以下表结构(经过简化,所有不相关的列都从每个表中删除一列):

class Customer(db.Model):
    __tablename__ = 'customers'
    id = db.Column(db.Integer, primary_key=True)
    identification_num = db.Column(db.String(10), unique=True)
    name = db.Column(db.Text)
    invoices = db.relationship('Invoice', backref='customer')
    accounts = db.relationship('Account', backref='customer')

def __init__(self):
    pass

def __repr__(self):
    return '<Customer %r>' % (self.name)

class Invoice(db.Model):
    __tablename__ = 'invoices'
    id = db.Column(db.Integer, primary_key=True)
    customer_id = db.Column(db.Integer, db.ForeignKey('customers.id'))
    active = db.Column(db.Boolean)
    accounts = db.relationship('Account', backref='invoice')

    def __repr__(self):
        return '<Invoice %r>' % (self.id)

class Account(db.Model):
    __tablename__ = 'accounts'
    id = db.Column(db.Integer, primary_key=True)
    account_id = db.Column(db.Integer, unique=True)
    invoice_id = db.Column(db.Integer, db.ForeignKey('invoices.id'))
    user_id = db.Column(db.Integer, db.ForeignKey('customers.id'))
    active = db.Column(db.Boolean)
    subscriptions = db.relationship('Subscription', backref='account')

    def __repr__(self):
        return '<Account %r>' % (self.account_id)

class Subscription(db.Model):
    __tablename__ = 'subscriptions'
    id = db.Column(db.Integer, primary_key=True)
    account_id = db.Column(db.Integer, db.ForeignKey('accounts.account_id'))
    sub_active = db.Column(db.DateTime)
    telnums = db.relationship('Telnum', backref='subscription')

    def __repr__(self):
        return '<Subscription %r>' % (self.id)

class Telnum(db.Model):
    __tablename__ = 'pstn_numbers'
    id = db.Column(db.Integer, primary_key=True)
    sub_id = db.Column(db.Integer, db.ForeignKey('subscriptions.id'))
    telnum = db.Column(db.String(64))
    holder = db.Column(db.String(10))

    def __repr__(self):
        return '<Telnum %r>' % (self.telnum)

最佳答案

一般来说,我不会将间接关系定义为关系,因为您冒着这些间接关系变得不同步的风险当您进行修改时。您可以通过指定 viewonly=False 来解决其中的一些限制。 关系的参数。

一个更简单、风险更小、更直接的解决方案是使用查询(或启用查询的属性),以防您想从数据库中重新加载数据,并使用 python 列表推导来获取子-关系树的子子节点:

class Customer(Base):
    # ...

    @property
    def telnums_qry(self):
        sess = Session.object_session(self)
        return (sess.query(Telnum)
                .join(Subscription)
                .join(Account)
                .filter(Account.user_id == self.id)
                ).all()


    @property
    def telnums_mem(self):
        return [tel
                for acc in self.accounts
                for sub in acc.subscriptions
                for tel in sub.telnums
                ]


class Telnum(Base):
    # ...

    @property
    def customer(self):
        return (self.subscription
                and self.subscription.account
                and self.subscription.account.customer
                )

关于python - 如何使用多级/多连接在 SQLAlchemy 中指定表关系?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/22229099/

相关文章:

python - Flask-SQLAlchemy:sqlite3 IntegrityError

python - 使用 SQLAlchemy 预加载一组对象时出现问题

javascript - flask 倒计时

python - 使用 Python 向 Apple Notification Service 发送消息

python - 为什么pandas的dataframe列顺序会自动改变?

python - 如何在 Python 中转换指数并摆脱 'e+' ?

Python decimal 模块不一致

python - 如何根据字典列字段列表中的键值对过滤 DataFrame 行?

python - SQLAlchemy 查询与多列元组上的比较

python - 如何使用 Flask Request 将 GET 参数传递给 url