flask-sqlalchemy,选择使用反向包含(不在)中

时间:2015-09-09 09:31:08

标签: python flask flask-sqlalchemy

我有3个模特帖子,评论,用户:

class User(UserMixin, db.Model):
    __tablename__ = 'users'
    id = db.Column(db.Integer, primary_key=True)
    username = db.Column(db.String(64), unique=True, index=True)
    posts = db.relationship('Post', backref='author', lazy='dynamic')
    comments = db.relationship('Comment', backref='author', lazy='dynamic')

class Post(db.Model):
    __tablename__ = 'posts'
    id = db.Column(db.Integer, primary_key=True)
    body = db.Column(db.Text)
    author_id = db.Column(db.Integer, db.ForeignKey('users.id'))
    comments = db.relationship('Comment', backref='post', lazy='dynamic')

class Comment(db.Model):
    __tablename__ = 'comments'
    id = db.Column(db.Integer, primary_key=True)
    body = db.Column(db.Text)
    author_id = db.Column(db.Integer, db.ForeignKey('users.id'))
    post_id = db.Column(db.Integer, db.ForeignKey('posts.id'))

我的问题: 如何过滤那些未被给定用户评论的帖子(给定user.id)

我有一段代码用于过滤由给定用户评论的帖子:

@property
def commented_posts(self):
  return Post.query.join(Comment, Comment.post_id==Post.id).filter(Comment.author_id==self.id)

1 个答案:

答案 0 :(得分:0)

查找给定用户未在给定帖子上发表评论的所有帖子: db.session.query(Post)\ .filter(~exists().where(and_(Comment.author_id != some_user_id, Post.id == Comment.post_id))).all()

这会生成sql:

SELECT posts.id AS posts_id, posts.body AS posts_body, posts.author_id AS posts_author_id 
FROM posts 
WHERE NOT (EXISTS (SELECT * 
FROM comments 
WHERE comments.author_id != :author_id_1 AND posts.id = comments.post_id))

示例测试代码:

from sqlalchemy import exists, and_

u1 = User(username='User1')
u2 = User(username='User2')

db.session.add_all([u1, u2])
db.session.commit()

p1 = Post(body='Post1', author_id=u1.id, comments=[Comment(body='Comment1', author_id=u1.id),
     Comment(body='Comment2', author_id=u2.id)])
p2 = Post(body='Post2', author_id=u2.id, comments=[Comment(body='Comment3', author_id=u1.id)])
p3 = Post(body='Post3', author_id=u2.id)

db.session.add_all([p1, p2, p3])
db.session.commit()

result = db.session.query(Post)\
    .filter(~exists().where(and_(Comment.author_id != u1.id, Post.id == Comment.post_id))).all()

# Returns post  2 and post 3
print(result)

result = db.session.query(Post)\
    .filter(~exists().where(and_(Comment.author_id != u2.id, Post.id == Comment.post_id))).all()

# Returns post 3
print(result)