SQLAlchemy和join,我们没有外键

时间:2011-06-15 01:51:33

标签: python mysql join foreign-keys 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 个答案:

答案 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时),但无论如何你都可能遇到麻烦。