В обычном m2m у вас есть таблица ассоциации с путем соединения между двумя сущностями, которая четко определена внешними ключами. Таким образом, вы можете просто указать sqlalchemy, какую таблицу вы хотите использовать, чтобы связать две другие таблицы, и она сделает все остальное (как вы сделали здесь: secondary=categories_articles
). Присоединение User
к Article
с немного более сложное.
Вы хотите, чтобы между User
и Article
существовали отношения "многие ко многим", чтобы вы могли получать статьи, которые интересуют пользователей, на основе общих категорий. Или просто:
User
<===> some join path involving categories
<===> Article
.
Наша таблица user
имеет внешний ключ к таблице categories_users
, а наша таблица categories_articles
имеет внешний ключ к нашей таблице articles
. Самое главное, что и таблица categories_users
, и таблица categories_articles
имеют поле category_id
, поэтому мы можем объединить эти две таблицы.
Таким образом, вы можете добавить отношение articles
к вашей модели User
с помощью следующего кода:
articles = db.relationship(
'Article',
secondary=\
'join(categories_users, categories_articles, '
'categories_users.c.category_id==categories_articles.c.category_id)'
)
При доступе к атрибуту User.articles
выдается следующий SQL:
SELECT article.id AS article_id, article.name AS article_name
FROM article, categories_users
INNER JOIN categories_articles
ON categories_users.category_id = categories_articles.category_id
WHERE %(param_1)s = categories_users.user_id
AND article.id = categories_articles.article_id
где понятно, что происходит. categories_users
объединяется с categories_articles
, фактически создавая новую таблицу, в которой строки user
объединяются со строками article
в их общих категориях. Затем SQLAlchemy может рассматривать это как «нормальное» отношение «многие ко многим» с одной таблицей ассоциации и использовать существующие внешние ключи, чтобы собрать воедино остальные отношения и создать необходимый запрос.