【问题标题】:How can I search the table of a Flask SQLAlchemy many to many relationship?如何搜索 Flask SQLAlchemy 多对多关系的表?
【发布时间】:2026-01-05 01:20:05
【问题描述】:

我有以下型号和桌子:

chat_members = db.Table('chat_members',
    db.Column('user_id', db.Integer, db.ForeignKey('user.id')),
    db.Column('chat_id', db.Integer, db.ForeignKey('chat.id'))
)

class chat(db.Model):
    id = db.Column(db.Integer, primary_key=True)
    start_date = db.Column(db.DateTime)
    chat_memb = db.relationship('user', secondary=chat_members, backref=db.backref('members', lazy='dynamic'))  
    chat_line = db.relationship('line', backref='chat_line', lazy='dynamic')

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

class user(db.Model):
    id = db.Column(db.Integer, primary_key=True)
    user_email = db.Column(db.String, unique=True)
    user_password = db.Column(db.String)
    lines = db.relationship('line', backref='line_author', lazy='dynamic')

    def __repr__(self):
        return '<User %r>' % (self.user_email)

class line(db.Model):
    id = db.Column(db.Integer, primary_key=True)
    published_date = db.Column(db.DateTime)
    chat_id = db.Column(db.Integer, db.ForeignKey('chat.id'))
    sent_by = db.Column(db.Integer, db.ForeignKey('user.id'))
    line_text = db.Column(db.String)


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

我已成功将数据添加到所有这些模型,但无法查询表。查询的最终目标是查找与特定用户关联的所有聊天。这是我所做的:

first_user = user.query.get(1)
chat.query.filter(chat_members.any(chat_memb=first_user)).all()

我得到的

sqlalchemy.exc.InvalidRequestError:无法将集合与 物品或收藏品;使用 contains() 来测试成员资格。

这个问题(http://*.com/questions/12593421/sqlalchemy-and-flask-how-to-query-many-to-many-relationship)看起来非常相似,但是当我为我的模型复制它时,我做完后得到AttributeError: type object 'chat' has no attribute 'members'

chat.query.filter(chat.members.any(user_email='ACCEPTABLE_EMAIL')).all()

看到memberschat 模型中的反向引用,回溯出人意料,但我觉得这个查询很接近。

我能找到的其他相关问题似乎没有为同一搜索提供建议,而且我在官方或第三方多对多文档中找不到此类查询。

【问题讨论】:

    标签: python sqlalchemy flask


    【解决方案1】:

    您需要在查询中使用联接。首先将您的chat.chat_memb 关系更改为:

    # Change backref from 'members' to 'chats', since the backref will be pointing
    # to chat class.
    chat_memb = db.relationship('user', secondary=chat_members,
                                backref=db.backref('chats', lazy='dynamic'))
    

    然后使用这个查询:

    chat.query.join(user.chats).filter(user.id == 1).all()
    

    我还建议遵循 Python 样式指南并为类使用大写名称,例如Chat 而不是 chat。现在很容易混淆代码中的类和实例。

    【讨论】:

    • 完美——非常感谢您的回答和推荐。