sqlalchemy查询与map表的多对多关系

txu3uszq  于 2021-06-18  发布在  Mysql
关注(0)|答案(1)|浏览(338)

我有一个数据库模型(见下文)。我正在做一个项目,它应该根据用户指定的类别过滤查询结果-可以有几个类别与一个用户关联。换句话说,我想展示 UserArticles 与他/她指定的类别相匹配。 Articles 也可以与多个类别关联。如何使用sqlalchemy查询实现这一点?

categories_users = db.Table(
    'categories_users',
    db.Column('user_id', db.Integer(), db.ForeignKey('user.id')),
    db.Column('category_id', db.Integer(), db.ForeignKey('category.id'))
)

categories_articles = db.Table(
    'categories_articles',
    db.Column('article_id', db.Integer(), db.ForeignKey('article.id')),
    db.Column('category_id', db.Integer(), db.ForeignKey('category.id'))
)

class Category(db.Model):
    id = db.Column(db.Integer(), primary_key=True)
    name = db.Column(db.String(80), unique=True)
    articles = db.relationship('Article', secondary=categories_articles,
        backref=db.backref('categories', lazy='dynamic'))
    def __str__(self):
        return self.name

class Article(db.Model):
    id = db.Column(db.Integer, primary_key=True)
    name = db.Column(db.String(255))
    def __str__(self):
        return self.name

class User(db.Model):
    id = db.Column(db.Integer, primary_key=True)
    email = db.Column(db.String(255), unique=True, nullable=False)
    categories = db.relationship('Category', secondary=categories_users,
        backref=db.backref('users', lazy='dynamic'))
    def __str__(self):
        return self.email
cczfrluj

cczfrluj1#

在普通的m2m中,有一个关联表,其中两个实体之间的连接路径由外键明确定义。因此,您只需告诉sqlalchemy您要使用哪个表来关联另外两个表,其余的就由它来完成(正如您在这里所做的: secondary=categories_articles ). 加入 User 是的 Article s稍微复杂一点。
你想要一个多对多的关系 User 以及 Article ,这样就可以根据常见的分类得到用户感兴趣的文章。或者简单地说: User <===> some join path involving categories <===> Article .
我们的 user 表的外键是 categories_users table和我们的 categories_articles 表的外键是 articles table。最重要的是 categories_users table和table categories_articles 有table吗 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 做一张新table user 行与 article 行的公共类别。然后,sqlalchemy可以将其视为具有单个关联表的“普通”多对多关系,并利用现有的外键来拼凑关系的其余部分并构造必要的查询。

相关问题