У меня есть простое приложение новостей, где пользователи могут видеть последние сообщения, и им могут нравиться некоторые из этих сообщений.
Модели:
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
Я также видел этот ответ , который делает то же, что и мне нужно на уровне базы данных, но я хочу сделать это с SQLAlchemy
.
Заранее спасибо.