在SQLAlchemy中注释“exists”子查询

2024-03-28 18:07:55 发布

您现在位置:Python中文网/ 问答频道 /正文

我有一个简单的新闻应用程序,用户可以看到最新的帖子,他们可以喜欢其中的一些帖子。你知道吗

模型:

from sqlalchemy.orm import relationship, backref

from app import db


class User(db.Model):
    id = db.Column(db.Integer, primary_key=True)
    username = db.Column(db.String, nullable=False)
    ...

class Post(db.Model):
    id = db.Column(db.Integer, primary_key=True)
    title = db.Column(db.String)
    body = db.Column(db.String)
    ...

class Like(db.Model):
    id = db.Column(db.Integer, primary_key=True)
    user_id = db.Column(db.ForeignKey(User.id))
    post_id = db.Column(db.ForeignKey(Post.id))
    post = relationship(Post, backref=backref('likes'))

我试图实现的是用一个额外的字段来获取每个帖子,该字段指示登录用户是否喜欢该帖子,但以优化的方式进行,而不必对每个帖子进行查询。你知道吗

我尝试在模式级别使用marshmallow-sqlalchemy

from marshmallow import fields

from app import ma
from news.models import Post

class PostSchema(ma.ModelSchema):
    is_liked = fields.Method("get_is_liked")

    def get_is_liked(self, obj):
        user = self.context['user']
        return bool(Like.filter_by(user_id=user.id, post_id=obj.id).first())

    class Meta:
        model = Post

但这将导致每个帖子有N个查询。你知道吗

我还尝试像Django ORM中的注释一样实现这一点:

class PostListView(Resource):

    # I have the user object here using a decorator
    def get(self, user):
        # I know that this is a bad syntax
        query = Post.query(Post.likes.filter_by(user_id=user.id).exists().label('is_liked')))

        schema = PostSchema(strict=True, many=True, context={"user": user})
        result = schema.dump(query.all())

        return result.data

我还看到了这个answer,它在数据库级别的作用与我所需要的相同,但是我想用SQLAlchemy来实现它。你知道吗

提前谢谢。你知道吗


Tags: fromimportidtruedbmodeliscolumn
1条回答
网友
1楼 · 发布于 2024-03-28 18:07:55

这样行吗?我们的想法是加载post,这样Post.likes只包含当前用户喜欢post的情况。contains_eager('likes')应该加载Post中的likes数组。你知道吗

# user_id is the id of the current user
q = session.query(Post) \
           .outerjoin(Like, and_(Like.post_id == Post.id,
                                 Like.user_id == user_id)) \
           .options(contains_eager('likes'))

那么is_liked可以是return len(self.likes) > 0

相关问题 更多 >