首页 > 解决方案 > 从多对多关系中的两个表创建关联的 SQLAlchemy 查询是什么?

问题描述

因此,在尝试创建一个简单的 Web 应用程序的过程中,我一直在努力争取一天左右的时间。

我创建了如下所示的两个类(User 和 RaidItem)。我的意图是让任意数量的用户拥有 RaidItem 的“所有权”。在进行研究时,我发现需要关联表并创建了如下所示的表。

    association_table = db.Table('association',
                        db.Column('user_id', db.Integer(), db.ForeignKey('user.id')),
                        db.Column('raiditem_id', db.Integer(), db.ForeignKey('raid_item.id')))

    class User(db.Model, UserMixin):
        id = db.Column(db.Integer(), primary_key=True)
        items = db.relationship('RaidItem', secondary=association_table, backref = db.backref('owner'), lazy='dynamic')

    class RaidItem(db.Model):
        id = db.Column(db.Integer(), primary_key=True)
        name = db.Column(db.String(length=30), nullable=False, unique=False)

我创建了一个用户和几个已成功填充到我的数据库中的 RaidItem。

在我的一条路线中,我有一个部分显示“未拥有的物品”和“拥有的物品”。

我当前的“无主物品”查询如下所示:

items = RaidItem.query.filter(RaidItem.owners == None).all()

屏幕上显示“Unowned Items”,但我的逻辑是错误的,我不知道如何解决它。目前,无论用户如何,它都会显示所有“无主项目”,但我只想显示单个用户的“无主项目”。澄清一下,如果 user1 拥有 item1,user2 将无法看到 item1。那不是我的意图。

我的“自有物品”查询如下所示:

owned_items = RaidItem.query.join(association_table, (association_table.c.user_id == current_user.id)).filter(association_table.c.user_id == current_user.id)

如果不符合我的意图,即仅显示当前登录用户当前“拥有”的项目。

我的问题有两个:

1.) 在用户和创建的 RaidItem 之间创建关联的 SQLAlchemy 查询是什么——并且——

2.) 创建关联后,如何根据创建项目的“所有权”进行查询/过滤?

我已经在下面的评论中弄清楚了如何将数据手动插入关联表,但我仍然在努力让这些查询正确。任何帮助或指导将不胜感激,并感谢您的宝贵时间!

标签: pythonsqliteflaskflask-sqlalchemy

解决方案


因此,我通过研究 SQL 查询以及如何利用 db.engine.execute() 找出了我的问题。下面的代码是我为了使用原始 SQL 进行故障排除而提出的:

owned_items = db.engine.execute(f'SELECT association.raiditem_id 
                                  FROM association 
                                  JOIN user 
                                  ON association.user_id = user.id 
                                  WHERE user.id = {current_user.id}')

唯一的问题是这个方法实际上并没有正确引用存储在数据库中的对象。我能够使用下面的 SQLAlchemy 查询来正确执行此操作:

owned_items = RaidItem.query.join(association_table).join(User).filter(association_table.c.user_id == current_user.id).all()

我希望这对将来的人有所帮助。


推荐阅读