[ SQLAlchemy ] 关于dynamic的“一知半解”
问题提出:
1.粉丝机制
2.评论的点赞功能
这两个功能分别由User类和Comment类来实现,同样定义了多对多的关系,查询的时候用的方法却大不一样,先看看代码吧。
### # User类的中间表 followers = db.Table( 'followers', db.Column('follower_id', db.Integer, db.ForeignKey('users.id')), db.Column('followed_id', db.Integer, db.ForeignKey('users.id')), db.Column('timestamp', db.DateTime, default=datetime.utcnow) ) # Comment类的中间表 comments_likes = db.Table( 'comments_likes', db.Column('user_id', db.Integer, db.ForeignKey('users.id')), db.Column('comment_id', db.Integer, db.ForeignKey('comments.id')), db.Column('timestamp', db.DateTime, default=datetime.utcnow) ) ### class User(PaginatedAPIMixin, db.Model): ... # followeds 是该用户关注了哪些用户列表 # followers 是该用户的粉丝列表 followeds = db.relationship( 'User', secondary=followers, primaryjoin=(followers.c.follower_id == id), secondaryjoin=(followers.c.followed_id == id), backref=db.backref('followers', lazy='dynamic'), lazy='dynamic') def is_following(self,user): ''' 判断有没有关注 user 这个用户 ''' return self.followeds.filter(followers.c.followed_id == user.id).count()>0 class Comment(PaginatedAPIMixin, db.Model): __tablename__ = 'comments' id = db.Column(db.Integer, primary_key=True) body = db.Column(db.Text) ... likers = db.relationship( 'User', secondary=comments_likes, backref=db.backref('liked_comments',lazy='dynamic') ) def is_liked_by(self, user): ''' 判断用户 user 是否已经对该评论点过赞 ''' return user in self.likers
从上面的代码看出,同样是多对多的关系
为何User类中高亮部分的followeds是可查询的对象
而Comment类中高亮部分的likers是列表呢?
原因分析
1.先看User类中定义的followeds,正向查询(使用user.followeds)的时候会用到 lazy='dynamic' ,反向查询(使用user.followers)的时候同样也会用到。
2.再看Comment类中定义的likers,只有反向查询的时候才会用到 lazy='dynamic'
所以说,关键在于是否用到 lazy='dynamic' 。
查看flask-SQLAlchemy文档http://www.pythondoc.com/flask-sqlalchemy/models.html#one-to-many :
'dynamic' 在有多条数据的时候是特别有用的。不是直接加载这些数据,SQLAlchemy 会返回一个查询对象,在加载数据前您可以过滤(提取)它们。