SQLAlchemy与联接,我们没有外键
假设在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]})
... 但显然我误解了文档的意思。
提前感谢任何帮助。
1 个回答
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 会假装这个外键确实存在,尽管实际的数据库里没有。当然,如果这个隐含的外键约束被违反了(比如 comments.user_id
没有对应的 users.id
),你可能会遇到麻烦,但反正你可能已经有麻烦了。