2015-09-09 56 views
0

我有3種型號文,評論,網友:燒瓶SQLAlchemy中,選擇使用逆包容性(不)一套

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) 

回答

0

查找所有帖子其中給定用戶具有不COMME nted對特定職位: 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) 
+0

這不包括尚未被任何* *用戶評論的帖子。 – davidism

+0

這不會起作用,我們應該排除那些由給定用戶評論的帖子集合 –

+0

我已經更新了答案 –