Skip to main content
 首页 » 编程设计

python之如何搜索 Flask SQLAlchemy 多对多关系的表

2025年05月04日11wayfarer

我有以下模型和表格:

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: Can't compare a collection to an object or collection; use contains() to test for membership.

这个问题 (http://stackoverflow.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() 

当 members 是 chat 模型中的 backref 时,回溯令人惊讶,但我觉得这个查询很接近。

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

请您参考如下方法:

您需要在查询中使用联接。首先将您的 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。现在很容易混淆代码中的类和实例。