如何在Flask SQL Alchemy中查询一对多/多对多的关系?

时间:2016-08-29 12:24:54

标签: python flask sqlalchemy

这是两个在我的问题中很重要的数据库模型。

我建立了一对多的关系(对话可以有多个消息) 用户和对话之间还建立了多对多的关系。

获得两个用户对象后,比如说 user1 user2 ,我需要找到包含这两个用户的对话(如果存在)。在获得会话对象后,说 current_convo ,我还需要查询该会话中的所有消息。这两个查询怎么办?

class Conversation(db.Model):
    __tablename__ = 'conversation'

    id = db.Column('id', db.Integer, primary_key=True)
    users = db.relationship("User", secondary=relationship_table)
    messages = db.relationship("Message", backref="conversation", lazy="dynamic")


class Message(db.Model):
    __tablename__ = 'message'

    id = db.Column('id', db.Integer, primary_key=True)
    message = db.Column('message', db.String)
    timestamp = db.Column('timestamp', db.String)
    sender = db.Column('sender', db.String)
    conversation_id = db.Column(db.Integer, db.ForeignKey('conversation.id'))

class User(db.Model, UserMixin):
    __tablename__ = 'user'

    id = db.Column('id', db.Integer, primary_key=True)
    username = db.Column('username', db.String(100), unique=True, index=True)
    password = db.Column('password', db.String(100))
    email = db.Column('email', db.String(100), unique=True, index=True)
    authenticated = db.Column('authenticated', db.Boolean, default=False)

2 个答案:

答案 0 :(得分:2)

我知道这样做的最好方法是使用SQLAlchemy' contains

Conversation.query.filter(
    Conversation.users.contains(user1),
    Conversation.users.contains(user2)
)

答案 1 :(得分:-1)

这不是一个纯粹的SQL查询,但这是我如何使用Pandas完成你所要求的。

import pandas as pd
import sqlalchemy
import urllib

#setup vars and connection
server = 'myServer'
db = 'myDb'

user1 = 'someId1'
user2 = 'someId2'

#You'll have to maybe change this a little if you aren't using a trusted connection on SQL Server
connStr = 'DRIVER={SQL Server};SERVER=' + server + ';DATABASE=' + db + ';Trusted_Connection=yes'
conn = sqlalchemy.create_engine(
            'mssql+pyodbc:///?odbc_connect=%s' % (urllib.quote_plus(connStr)))

#select all conversations that have one of the users
query = """select * from Conversation where users is in ('{0}','{1}')""".format(user1,user2)
conv_df = pd.read_sql(query,conn)

#unstack the users, so we can see which users are part of the same conversation
conv_users = conv_df.set_index(['id','users']).unstack().reset_index()

#filter conversations to those that have both users
conv_together = conv_users[(conv_users[user1].notnull()) & (conv_users[user2].notnull())]

conv_list = conv_together['id'].tolist()
conv_str = "(" + ', '.join("'{0}'".format(w) for w in conv_list) +")"

#select all messages where the conv id matches your criteria (has both users)
query = """select * from Message where conversation_id is in {0}""".format(conv_str)

message_df = pd.read_sql(query,conn)

很难显示没有测试数据的中间步骤,因此我无法运行和QC此代码,但希望它能为您提供正确的想法。