使用 Flask、SqlAlchemy 和 Jinja2 在 ORM 中引用过滤器项
Posted
技术标签:
【中文标题】使用 Flask、SqlAlchemy 和 Jinja2 在 ORM 中引用过滤器项【英文标题】:Referencing filter items in ORM with Flask, SqlAlchemy and Jinja2 【发布时间】:2014-11-09 23:01:19 【问题描述】:我正在使用 Flask 来显示我从 API 收集的一些数据。它是饮料的形式,我已经有一个包含所有数据的 SQLlite 数据库。
信息存储在三个模型中,分别是配方、成分和风味
class Recipe(Base):
""""""
__tablename__ = "recipes"
id = Column(Integer, primary_key=True)
name = Column(Unicode(200), index=True, unique=True)
url = Column(String(200), index=True)
length = Column(String(120), index=True)
ingredients = relationship('Ingredient', backref='recipes', lazy='dynamic')
flavours = relationship('Flavour', backref='recipes', lazy='dynamic')
def __init__(self, name, url, length):
""""""
self.name = name
self.url = url
self.length = length
def __repr__(self):
return '<Recipe %s>' % (self.name)
class Ingredient(Base):
""""""
__tablename__ = "ingredients"
id = Column(Integer, primary_key=True)
name = Column(Unicode(200))
quantity = Column(String(200))
unit = Column(String(200))
recipe_id = Column(Integer, ForeignKey('recipes.id'))
def __init__(self, name, quantity, unit):
""""""
self.name = name
self.quantity = quantity
self.unit = unit
def __repr__(self):
return '<Ingredient %s>' % (self.name)
class Flavour(Base):
""""""
__tablename__ = "flavours"
id = Column(Integer, primary_key=True)
recipe_id = Column(Integer, ForeignKey('recipes.id'))
piquant = Column(String(200), index=True)
sour = Column(String(200), index=True)
salty = Column(String(200), index=True)
sweet = Column(String(200), index=True)
bitter = Column(String(200), index=True)
meaty = Column(String(200), index=True)
def __init__(self, piquant, sour, salty, sweet, bitter, meaty):
""""""
self.piquant = piquant
self.sour = sour
self.salty = salty
self.sweet = sweet
self.bitter = bitter
self.meaty = meaty
def __repr__(self):
return '<Flavour %s>' % (self.recipe_id)
我基本上是在尝试使用 Flask 模板呈现数据,并且通过查询配方的名称成功地做到了这一点。但是,我现在正在尝试查询一种成分,并在网页上呈现包含该成分的所有食谱。
在 Python shell 中,我已成功查询食谱和成分数据库以返回所有包含查询成分的食谱...
session.query(Recipe, Ingredient).filter(Recipe.id==Ingredient.recipe_id).filter(Ingredient.name.contains("gin")).all()
而且效果很好,返回类似于以下的输出:
(<Recipe Gin Rickey>, <Ingredient gin >), (<Recipe Gin Gimlet>, <Ingredient gin >)
基本上,我只想在页面上呈现配方模型信息,而不仅仅是成分模型信息。
@app.route('/search/ingredient/<query>')
def searchingredient(query):
recipe = session.query(Recipe, Ingredient).filter(Recipe.id==Ingredient.recipe_id).filter(Ingredient.name.contains(query)).all()
title = "Gin"
return render_template('query.html', recipes=recipe, title=title)
作为 Flask 和 Jinja 的新手,我不知道在 html 页面上呈现这个以包括食谱名称、食谱网址、食谱成分、食谱口味。我已经到了这一步,但它真的不起作用......
<html>
<head>
% block head %
<title>% block title %% endblock % - My Application</title>
% endblock %
</head>
<body>
% block body %
% if recipes %
% for recipe in recipes %
recipe['name']
% endfor %
% endif %
% endblock %
</body>
</html>
如果有人能指出我正确的方向,那就太好了。我可以根据需要提供更多信息。
【问题讨论】:
【参考方案1】:您的查询虽然可能有效,但格式不正确。如果您正在对其进行过滤并且只想要配方,则无需选择成分。现在您需要进行元组解包的原因是因为您将获得一个 2 元组列表作为结果(配方、成分对)。相反,只选择配方并加入成分关系。
recipes = session.query(Recipe).join(Recipe.ingredients).filter(
Ingredient.name.contains('gin')
).all()
或者,效率稍低,但更清楚的是,您可以直接过滤关系。
recipes = session.query(Reciope).filter(
Recipe.ingredients.any(Ingredient.name.contains('gin'))
).all()
【讨论】:
【参考方案2】:我现在找到了解决此问题的方法
% for key, value in recipes %
key.name
key.url
% endfor %
我没有意识到可以在 Jinja 中以这种方式使用键值对。这个的输出是:
Gin Rickey http://www.foodrepublic.com/2012/06/28/gin-rickey-recipe Gin Gimlet http://www.marthastewart.com/345584/gin-gimlet
等等。
【讨论】:
以上是关于使用 Flask、SqlAlchemy 和 Jinja2 在 ORM 中引用过滤器项的主要内容,如果未能解决你的问题,请参考以下文章
flask_sqlalchemy和sqlalchemy联系区别及其使用方式