使用 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使用方法

flask-sqlalchemy

flask_sqlalchemy和sqlalchemy联系区别及其使用方式

Python flask-sqlalchemy初级解析

flask-sqlalchemy 和sqlalchemy的区别

Flask 学习-19.配置管理flask_sqlalchemy 和 flask_migrate