2011-06-15 36 views
8

假设在MySQL中以下内容:SQLAlchemy的和连接,我们没有任何外键

CREATE TABLE users (
    id integer auto_increment primary key, 
    username varchar(30), 
    active enum('N','Y'), 
    created_on int(11), 
    updated_on int(11), 
    points int(10), 
    // other fields 
); 

CREATE TABLE comments (
    id integer auto_increment primary key, 
    user_id integer, 
    forum_id integer, 
    favorited integer, 
    // other fields 
); 

注意,没有正式的外键约束添加到表。这是我继承的东西,不能改变我们目前的设置。 (我们正在对整个系统进行检修,但同时我必须使用我已经提供的工作)

当我在表之间没有建立正式的外键时,我无法绕过SQLalchemy的连接。

实际上,我想这样做:

SELECT 
    u.username, 
    c.forum_id, 
    count(c.id) 
FROM 
    users u 
    JOIN comments c ON u.id=c.user_id 
WHERE 
    u.id = 1234 
GROUP BY 
    u.username, 
    c.forum_id; 

代码我有包括像以下:

mapper(Users, users, primary_key=[users.c.id], 
    include_properties=['user_id', 'username', 'active', 'created_on', 
     'updated_on', 'points']) 
mapper(Comments, comments, primary_key=[comments.c.id], 
    include_properties=['active', 'user_id', 'favorited', 'forum_id']) 

j = join(users, comments) 
mapper(UserComments, j, properties={'user_id': [users.c.id, 
    comments.c.user_id]}) 

session = create_session() 
query = session.query(UserComments).filter(users.cid == 1234) 
rdata = run(query) 
for row in rdata: 
    print row 

...这当然失败:

sqlalchemy.exc.ArgumentError: Can't find any foreign key relationships 
between 'users' and 'comments'. 

我不知道如何解决这个问题,当我们没有外键。我还怎么定义这种关系?我认为它是mapper()调用的一部分:

mapper(UserComments, j, properties={'user_id': [users.c.id, 
    comments.c.user_id]}) 

......但显然我误解了文档。

在此先感谢您的帮助。

+0

您确定要实际映射连接表达式吗?尽管SQLAlchemy允许这样做,但可能更有意义的做一些事情,比如'session.query([Users,Comments])。join(Comments,...)',以便最终得到用户和评论模型的实例科学怪人。另外,由于连接子句没有主键,因此生成的模型不太实用,因此不能对该模型持续进行修改。 – SingleNegationElimination 2011-06-15 03:01:56

回答

25

您有两种选择。您可以通过加入条件join像这样:

j = join(users, comments, onclause=users.c.id == commends.c.user_id) 

如果你在一个orm.relationship属性来定义这一点,关键字参数将primaryjoin而不是onclause

但是,我喜欢的方法只是谎言。通知SQLAlchemy有外键,即使没有。  

comments = Table('comments', metadata, 
    Column('id', Integer, primary_key=True), 
    Column('user_id', Integer, ForeignKey('users.id')), 
    ... 
) 

的SQLAlchemy将继续为如果外键实际上是现在,即使实际的数据库没有说。当然,如果隐含的foriegn键约束被违反(comments.user_id没有相应的users.id),您可能会遇到麻烦,但无论如何您可能会遇到麻烦。

+1

我尝试了使用'onclause'的第一个解决方案,但是遇到了一个'TypeError'。为了解决这个问题,我删除了'onclause'关键字,并将'users.c.id == commends.c.user_id'作为参数传递。 – 2015-12-08 13:31:59