“RelationshipProperty”对象不可迭代 - Flask Api - SQLAlchemy

3

我帮助开发一款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):

__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 编程。

希望你能帮忙! :) 我该如何使用餐费价格进行查询?

1个回答

0

简短回答:

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

详细回答:

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

这样就可以使得你的mealprice可查询,因为它现在是一个列。然而,在当前数据库状态下,你会遇到问题,因为你的mealprice是查询结果中列的总和。

你收到的错误TypeError是因为你混合了查询和数字,并且它们在对象构建之后进行评估。所以当你定义mealprice时(在构建过程中),recipe.ingredients.price是一个查询,但在json中变成了一个列表。

编辑:

个人而言,我建议将关注点分开,暂时避免使用混合属性,因为它们可能会模糊数据库和Python之间的界限。如果你的ingredients可能会发生变化,我会做如下处理:

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)

你可以从那里开始实现混合属性,如果你想的话。

哦,谢谢!那很有道理 :) 但是如何构建一个带有可工作的求和函数的数据库呢?你能给我一个包含两个模型的简单示例吗? - Tommotmot
onupdate是一个在对象更新时触发的函数,请确保使用函数本身而不是结果。它是calc_mealprice,而不是calc_mealprice()。http://docs.sqlalchemy.org/en/latest/core/defaults.html#python-executed-functions - S.Comeau
也许你不能将函数作为类的成员,所以也试试这个吧。 - S.Comeau
哦,S.Comeau非常感谢你的回答,但是现在我遇到了一个错误:尝试使用flask-admin更新我的数据库时出现AttributeError: 'NoneType'对象没有'price'属性。 - Tommotmot
好的,我在我的示例中修复了问题。享受吧! - S.Comeau
显示剩余2条评论

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接