【发布时间】:2015-01-31 05:40:19
【问题描述】:
我使用 sql Alchemy 有一个简单的多对多关系,如下所示:
file_favorites = db.Table('file_favorites',
db.Column('file_id', db.Integer(), db.ForeignKey('file.id')),
db.Column('user_id', db.Integer(), db.ForeignKey('user.id')),
db.Column('created_at', db.DateTime(), default=db.func.now()))
class File(db.Model, helpers.ModelMixin):
id = db.Column(db.Integer, primary_key=True, autoincrement=True)
name = db.Column(db.Unicode, nullable=False)
description = db.Column(db.Unicode, nullable=False)
created_at = db.Column(db.DateTime(), default=func.now())
last_updated = db.Column(db.DateTime(), default=func.now(), onupdate=func.now())
user_id = db.Column('user_id', db.Integer(), db.ForeignKey('user.id'), nullable=False, index=True)
user = db.relationship('User')
favorited_by = db.relationship('User', secondary=file_favorites, lazy='dynamic')
def is_favorite_of(self, user):
query = File.query
query = query.join(file_favorites)
query = query.filter(file_favorites.c.file_id == self.id)
query = query.filter(file_favorites.c.user_id == user.id)
return query.count() > 0
def favorite(self, user):
if not self.is_favorite_of(user):
self.favorited_by.append(user)
def unfavorite(self, user):
if self.is_favorite_of(user):
self.favorited_by.remove(user)
我希望访问 favorited_by 属性会导致查询尝试返回收藏此文件的用户列表。但是,查询似乎只访问了收藏此文件的第一个用户。我对此感到困惑,并期望我没有正确理解 sqlalchemy 关系。这是我正在经历的结果:
def create_model(model_class, *args, **kwargs):
model = model_class(*args, **kwargs)
db.session.add(model)
db.session.commit()
return model
def test_favorited_by(self):
user = create_model(User, username='user', email='user@user.net', password='password')
user1 = create_model(User, username='user1', email='user1@user.net', password='password')
user2 = create_model(User, username='user2', email='user2@user.net', password='password')
file = create_model(File, name='file', description='a description', user=user)
file.favorite(user1)
file.favorite(user)
file.favorite(user2)
db.session.commit()
print file.favorited_by
这个查询的结果:
SELECT "user".id AS user_id, "user".email AS user_email, "user".username AS user_username, "user".password AS user_password, "user".active AS user_active, "user".last_login_at AS user_last_login_at, "user".current_login_at AS user_current_login_at, "user".last_login_ip AS user_last_login_ip, "user".current_login_ip AS user_current_login_ip, "user".login_count AS user_login_count, "user".last_updated AS user_last_updated, "user".created_at AS user_created_at
FROM "user", file_favorites
WHERE :param_1 = file_favorites.file_id AND "user".id = file_favorites.user_id
最终返回user1,如果顺序切换,第一个收藏文件的用户永远是返回的用户。
【问题讨论】:
-
如果打印
file.favorited_by.all()会发生什么? -
Printing file.favorited_by.all() 返回:[
] 列表中的单个用户对象,匹配 user1,第一个收藏的用户。 -
File.favorite长什么样子?我的猜测是它正在做类似self.favorited_by = user而不是self.favorited_by.append(user)。 -
为了清晰起见,我在代码中添加了最喜欢、最不喜欢和最喜欢的方法。我正在使用附加,而不是等于。使用 is_favorite_of(user) 返回 true,这似乎是正确填充了关系表
标签: python flask sqlalchemy many-to-many