SQLAlchemy и присоединения, у нас нет внешних ключей - PullRequest
8 голосов
/ 15 июня 2011

Предположим в 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 голосов
/ 15 июня 2011

У вас есть два варианта.Вы можете передать условие соединения в 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), но, возможно, у вас все равно будут проблемы.

...