如何自动填充sqlalchemy列的值

时间:2019-02-18 13:56:17

标签: mysql sqlalchemy flask-sqlalchemy

我正在处理电子商务应用程序的数据库,在Order表(父级)和OrderItem表(子级)之间使用SQLAlchemy relationship()有一对多关系)。

数据库:

class Order(db.Model):
    id = db.Column(db.Integer, primary_key=True)
    customer_id = db.Column(db.Integer, db.ForeignKey('customer.id'), nullable=False)
    total = db.Column(db.Integer, nullable=False)
    submitted_on = db.Column(db.DateTime, nullable=False, default=datetime.utcnow)
    delivery_charges = db.Column(db.Integer, nullable=False)
    sub_total = db.Column(db.Integer, nullable=False)  # needs to be calculated automatically
    total_quantity = db.Column(db.Integer, nullable=False)  # needs to be calculated automatically
    order_items = db.relationship('OrderItem', backref='order', lazy=True)

    def __init__(self, customer_id, delivery_charges, sub_total, total_quantity):
        self.customer_id = customer_id
        self.delivery_charges = delivery_charges
        self.sub_total = sub_total
        self.total_quantity = total_quantity
        self.total = delivery_charges + sub_total


class OrderItem(db.Model):
    __tablename__ = "order_item"
    id = db.Column(db.Integer, primary_key=True)
    order_id = db.Column(db.Integer, db.ForeignKey('order.id'), nullable=False)
    product_size_color_id = db.Column(db.Integer, db.ForeignKey('product_size_color.id'), nullable=False)
    sale_id = db.Column(db.Integer, db.ForeignKey('sale.id'), nullable=True, default=None)
    selling_price = db.Column(db.Integer, nullable=False)  # needs to be calculated automatically
    quantity = db.Column(db.Integer, nullable=False)

我想做的是:我希望某些列根据其他表中的值自动计算,例如:

-Order.total_quantity:对应于同一order_item.quantity实例的每个Order的总和

-Order.sub_total:对应于同一order_item.selling_price实例的每个Order的总和。

-Order_item.selling_price:...

我使用default使某些列像Order.submitted_on中那样自动坐着,并使用类__init__中的Order函数来计算Order.total的值,如this question,但是,这两种方法仅在值与类/表本身一起使用时才起作用,我的问题是:如何根据其他表的值自动设置列的值?!

我在列Order.total_quantity上尝试了以下代码,该列用零填充!

    def __init__(self, customer_id, delivery_charges, sub_total):
        self.customer_id = customer_id
        self.delivery_charges = delivery_charges
        self.sub_total = sub_total
        order_items = self.order_items
        self.total_quantity = sum([i.quantity for i in order_items])
        self.total = delivery_charges + sub_total

我想做的是可能的吗?怎么样?

1 个答案:

答案 0 :(得分:0)

问题在于,当初始化Order对象时,尚无关联的order_items。除非您猜测order_id是什么,否则您不可能创建任何东西,而且这似乎很有风险。除了在init上运行外,为什么不使它在添加所有项目后运行更新数量方法?

例如:

class Order(Model):
    # your code as-is

    def update_total(self):
        self.total_quantity = sum([i.quantity for i in self.order_items])
        self.total = self.delivery_charges + self.sub_total

该方法正好是您已经提出的方法,就在__init__之外,因为您需要在添加项目后 对其进行调用。实际上,我将完全删除您的__init__-这样一来,您可以在需要时更改总计(例如,您需要在创建订单后到结帐之前将订单添加到订单中),然后调用{{ 1}},以获取所有最新信息。

您还可以考虑创建一种添加项目的方法,并使用该方法添加项目并同时更新总计。您可以使用它来自动计算任意数量的项目类型(我假设为ProductSizeColor)的价格。我称此为“ line_total”,但是您可以使用任何对您有意义的内容。

update_total()

然后实时:

class OrderItem(Model):
    __tablename__ = 'order_item'
    id = Column(Integer, primary_key=True)
    order_id = Column(Integer, ForeignKey('order.id'))
    product_size_color_id = Column(Integer, ForeignKey('product_size_color.id'))
    product_size_color = relationship('ProductSizeColor')
    # would it make more sense for the sale to be associated with the order
    # instead of the order item?
    sale_id = Column(Integer, ForeignKey('sale.id'))
    quantity = Column(Integer)
    line_total = Column(Integer)

class Order(Model):
    # other code

    def update_total(self):
        self.total_quantity = sum([i.quantity for i in self.order_items])
        self.sub_total = sum([i.line_total for i in self.order_items])
        self.total = self.delivery_charges + self.sub_total

    def add_item(self, session, psi_id, quantity):
        s = session
        order_item = OrderItem(
            order_id = self.id,
            product_size_color_id = psi_id,
            quantity = quantity
        )
        s.add(order_item)
        line_total = order_item.product_size_color.selling_price * quantity
        order_item.line_total = line_total
        self.update_total()

我们只添加了10的ProductSizeColor编号和10的ProductSizeColor编号2,并更新了商品总数,每种产品的总数以及整个订单的总数。