как автоматически заполнить значения столбцов sqlalchemy - PullRequest
0 голосов
/ 18 февраля 2019

Я работаю над базой данных приложения электронной коммерции, у меня есть отношение «Один ко многим» - с помощью SQLAlchemy отношение () - между таблицей Order (родительская) и таблицей OrderItem (дочерняя)).

База данных:

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, как ответили в на этот вопрос . Однако эти два метода работают только в том случае, если значения находятся внутри самого класса / таблицы, мой вопрос: как я могу автоматически устанавливать значения для столбцов в зависимости от другихзначения таблиц? !!

Я попробовал следующий код в столбце 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 голосов
/ 19 февраля 2019

Проблема в том, что когда вы инициализируете объект 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__ - таким образом, вы можете изменить итоги в любое время (скажем, вам нужно добавить элемент в заказ позже после его создания, но перед закрытием) и вызвать update_total() дляполучить все самое современное.

Вы можете также рассмотреть возможность создания метода для добавления элемента и использовать его для добавления элемента и одновременного обновления итогов.Вы можете использовать это, чтобы автоматически рассчитать цену для любого количества типов элементов (которое я предполагаю равным ProductSizeColor).Я назвал это «line_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()

Затем в режиме реального времени:

s = session()
order = Order(customer_id=customer_id, delivery_charges=delivery_charges,
              sub_total=sub_total)
s.add(order)
order.add_item(s, 1, 10)
order.add_item(s, 2, 8)
s.commit()

Мы только что добавили 10 из любого ProductSizeColor номер 1is и 8 ProductSizeColor номер 2, и обновлено общее количество товаров, общее количество для каждого продукта и общее количество для всего заказа.

...