在MySQL中假设以下内容:
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 :(得分: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
时),但无论如何你都可能遇到麻烦。