【问题标题】:'RelationshipProperty' object is not iterable - Flask Api - sqlalchemy'RelationshipProperty' 对象不可迭代 - Flask Api - sqlalchemy
【发布时间】:2018-05-14 19:18:06
【问题描述】:

:)

我开发了一个带有膳食价格计算功能的 Android Cook-App。

我几乎完成了我的 Api,但现在我得到一个 TypeError: 'RelationshipProperty' object is not iterable。

我的 sum(mealprice) 我有我的 json,但我喜欢用

查询我的 mealprice
@classmethod
def find_by_mealprice(cls, mealprice):
    return cls.query.filter_by(mealprice=mealprice).first()

但我只能在 json 方法中建立我的总和。

类 MealModel(db.Model):

__tablename__ = 'meal'

id = db.Column(db.Integer, primary_key=True)
name = db.Column(db.String(80))
description = db.Column(db.String)
usp = db.Column(db.String)
workTime = db.Column(db.TIME)
mainIngredients =db.Column(db.String)
img = db.Column(db.String)

difficulty_id = db.Column(db.Integer, db.ForeignKey('difficulty.id'))
difficulty = db.relationship('DifficultyModel')

diet_id = db.Column(db.Integer, db.ForeignKey('diet.id'))
diet = db.relationship('DietModel')

category_id = db.Column(db.Integer, db.ForeignKey('category.id'))
category = db.relationship('CategoryModel')

recipes = db.relationship('RecipeModel', lazy="dynamic")

mealprice = (sum([(recipe.ingredients.price/recipe.ingredients.minamount * recipe.quantity) for recipe in recipes])) <-- TypeError?


def __repr__(self):
    return (self.name)



def json(self):

    mealprice = (sum([(recipe.ingredients.price/recipe.ingredients.minamount * recipe.quantity) for recipe in self.recipes]))

    return {    'id': self.id, 
                'name': self.name, 
                'mIng': self.mainIngredients, 
                'usp': self.usp,
                'difficulty': self.difficulty.name,
                'workTime': self.workTime.isoformat(),
                'diet': self.diet.name,
                'description': self.description,
                'mealImage': self.img,
                'category': self.category.name,
                'recipes': [recipe.json() for recipe in self.recipes],
                'meal_price': mealprice
            }

我希望这个问题不是愚蠢的,我是 Flask Api 和 Python 的新手,几个月前我开始使用 Android Studio 编程。

希望你能帮上忙! :) 怎么查询mealprice??

【问题讨论】:

    标签: python flask flask-sqlalchemy


    【解决方案1】:

    简答:

    您没有将要查询的列包含在表中。

    长答案:

    SQLAlchemy 可帮助您转换数据库中的模型,以便将它们移动到 Python 代码中的类中,这样两者就可以非常神奇地交互。您可以使用 python 来扩展使用 SQLAlchemy 生成的模型,就像您在声明 mealprice 和 json 时所做的那样。您还可以重载现有属性,就像使用 repr 一样。

    为了能够查询一个属性,你必须使它成为 SQLAlchemy 意义上的属性,也就是一个列。当你这样做时:

    category_id = db.Column(db.Integer, db.ForeignKey('category.id'))
    

    你在 python 中创建一个 category_id 属性,基于一个 db.Column,它是一个 SQLAlchemy 属性,因此你可以对它进行查询。

    换句话说,如果你这样做:

    mealprice = db.Column(db.Numeric, default=calc_mealprice, onupdate=calc_mealprice)
    

    你可以随心所欲地定义你的功能,http://docs.sqlalchemy.org/en/latest/core/defaults.html

    这将使您的饭菜价格可查询,因为它现在是一列。但是,您将无法在当前数据库状态下创建函数,因为您的饭菜价格是查询结果中各列的总和。

    您收到的错误 TypeError 是因为您将查询与数字混合在一起,并且在构造对象后对它们进行评估。所以recipe.ingredients.price在定义mealprice时是一个查询(在构造期间),但在json期间变成了一个列表。

    编辑:

    就个人而言,我暂时将关注点分开并避免使用混合属性,因为它们可能会模糊数据库和 python 之间的界限。如果您的成分可能会发生变化,我会这样做:

    def calc_price_by_minamount(context):
        price = context.get_current_parameters()['price']
        minamount = context.get_current_parameters()['minamount']
        return price / ingredient.minamount
    
    class IngredientModel(db.Model):
        ...
        price_by_minamount = db.Column(db.Numeric,
                                       default=calc_price_by_minamount, 
                                       onupdate=calc_price_by_minamount)
    
    def calc_price(context):
        ingredients = context.get_current_parameters()['ingredients']
        quantity = context.get_current_parameters()['quantity']
        return sum([ingredient.price_by_minamount 
                    for ingredient 
                    in ingredients]) * quantity
    
    class RecipeModel(db.Model):
        ...
        price = db.Column(db.Numeric, 
                          default=calc_price, 
                          onupdate=calc_price)
    
    def calc_mealprice(context):
        recipes = context.get_current_parameters()['recipes']
        return sum([recipe.price for recipe in recipes])
    
    class MealModel(db.Model):
        ...
        mealprice = db.Column(db.Numeric, 
                              default=calc_mealprice, 
                              onupdate=calc_mealprice)
    

    如果需要,您可以从那里开始实现混合属性。

    【讨论】:

    • 不错的答案,但是当一种成分的价格更新时会发生什么?然后,mealprice 列将过时。解决此问题的更好方法是查看 SQLalchemy's hybrid attributes,它的行为有点像列,但实际上不是列。
    • 哦,谢谢!这是有道理的 :) 但是如何构建具有工作总和功能的数据库呢?你能给我一个简单的例子吗? 2个模型?
    • 哦,太好了,非常感谢 S.Comeau!但我得到 null - 我什么时候可以使用“onupdate”?
    • onupdate 是在对象更新时触发的函数,请确保您使用的是函数,而不是结果。它是 calc_mealprice,而不是 calc_mealprice() docs.sqlalchemy.org/en/latest/core/…
    • 也许你不能把函数作为一个类的成员,所以也试试这个
    猜你喜欢
    • 2021-12-25
    • 2013-11-07
    • 2015-02-06
    • 2016-05-30
    • 2014-01-07
    • 2012-08-01
    • 2021-08-23
    • 2021-08-20
    • 2020-06-04
    相关资源
    最近更新 更多