我有以下SQL请求,它给了我想要的结果,但我无法成功使它在SQLAlchemy中工作。
from flask_sqlalchemy import SQLAlchemy
from sqlalchemy.orm import relationship
db = SQLAlchemy()
class Article(db.Model):
id = db.Column(db.Integer, primary_key=True)
title = db.Column(db.String(255), nullable=False)
description = db.Column(db.Text)
image = db.Column(db.String(255))
brand = db.Column(db.String(255), nullable=False)
category_id = db.Column(db.Integer, db.ForeignKey("category.id"), nullable=False)
prices = relationship("ArticlePrice", cascade="all, delete-orphan")
class ArticlePrice(db.Model):
article_id = db.Column(db.Integer, db.ForeignKey("article.id"), primary_key=True)
location_id = db.Column(db.Integer, db.ForeignKey("location.id"), primary_key=True)
price = db.Column(db.Float, nullable=False)
active = db.Column(db.Boolean, nullable=False)
location = relationship('Location')
我想返回所有文章信息,这些信息位于给定位置并在此位置有效。加上price
,仅此地点的价格。
SELECT a.*, ap.price
FROM article a
INNER JOIN article_prices ap ON a.id = ap.article_id
WHERE ap.location_id = 1
AND ap.active = true
@namespace.route('/location/<location_id>')
class ArticleLocatedAPI():
@namespace.marshal_list_with(article, envelope='articles')
def get(self, location_id):
return Article.query.filter(Article.prices.any(active=True, location_id=location_id)).all()
正如您所看到的,我希望price
找到的文章不是relationship
,而是会返回价格数组。
article = namespace.model('Article', {
'id': fields.Integer,
'title': fields.String,
'description': fields.String,
'image': fields.String,
'brand': fields.String,
'price': fields.Float,
'category_id': fields.Integer
})
上面的代码给了我正确的文章。问题是它正在给我relationship
,这给了我一系列的价格。我想返回找到的文章的price
。我怎么在SQLAlchemy中写这个?
这是正确的方法吗?
答案 0 :(得分:3)
您可以使用明确的join()
结合contains_eager()
选项将Article.prices
集合限制为所有价格的子集,如"Using contains_eager() to load a custom-filtered collection result"中所述:
return Article.query.\
join(Article.prices).\
filter_by(active=True, location_id=location_id).\
options(db.contains_eager(Article.prices).load_only("price")).\
all()
filter_by()
从Query
的主要实体或最后一次加入的目标实体(在本例中为ArticlePrice
)中提取其关键字参数。使用load_only()
可以限制要从ArticlePrice
加载的属性集。除ArticlePrice
- you're using an ORM after all的主键外,所生成的SQL与原始SQL完全相同:
SELECT article_price.article_id AS article_price_article_id, article_price.location_id AS article_price_location_id, article_price.price AS article_price_price, article.id AS article_id, article.title AS article_title, article.description AS article_description, article.image AS article_image, article.brand AS article_brand, article.category_id AS article_category_id
FROM article JOIN article_price ON article.id = article_price.article_id
WHERE article_price.active = 1 AND article_price.location_id = ?
要rename并将价格集合解压缩到标量,请将attribute=
关键字参数传递给字段构造函数:
article = namespace.model('Article', {
'id': fields.Integer,
'title': fields.String,
'description': fields.String,
'image': fields.String,
'brand': fields.String,
'price': fields.Float(attribute=lambda a: a.prices[0].price),
'category_id': fields.Integer
})