【问题标题】:Flask SQLAlchemy One to Many Relationship QueryFlask SQLAlchemy 一对多关系查询
【发布时间】:2020-07-05 04:01:58
【问题描述】:

购物车项目是添加到购物车的产品。

当产品被添加到购物车时,我会期待一个警报,例如 CartItem ID: 1 被添加到购物车。如果再次添加相同的产品,我应该会收到警报 CartItem ID: 1 is already in cart。

现在,当我将相同的产品添加到购物车时,我收到 500 错误。我应该如何查询cart_item?

models.py

...
class Cart(db.Model):
    __tablename__ = 'cart'
    id = db.Column(db.Integer, primary_key=True)
    user_id = db.Column(db.Integer, db.ForeignKey('user.id'))
    cart_items = db.relationship('CartItem', 
        foreign_keys='CartItem.cart_id', backref='cart', lazy='dynamic', cascade='all, delete-orphan')

    def __repr__(self):
        return '<Cart {}>'.format(self.user_id)


class CartItem(db.Model):
    __tablename__ = 'cart_item'
    id = db.Column(db.Integer, primary_key=True)
    product_id = db.Column(db.Integer, db.ForeignKey('product.id'))
    product = db.relationship('Product', backref=db.backref('cart_item', uselist=False)) 
    cart_id = db.Column(db.Integer, db.ForeignKey('cart.id'))

    def __repr__(self):
        return '<CartItem {}>'.format(self.product_id)
...

routes.py

...
@cart_blueprint.route('/add_item/<int:product_id>', methods=['GET', 'POST'])
@login_required
def add_item(product_id):
    product = Product.query.get_or_404(product_id)
    cart_id = current_user.id
    cart = Cart.query.get(int(cart_id))
    cart_item = {}
    
    if any(product.id==cart_item.product_id for cart_item in cart.cart_items):
        cart_item = CartItem.query.join(CartItem.product).filter(Product.id==cart_item.product_id).first()
        flash(f'CartItem ID: {cart_item.id} already in cart')
...

回溯错误

cart_item = CartItem.query.join(CartItem.product).filter(Product.id==cart_item.product_id).first() AttributeError:“dict”对象没有属性“product_id”

【问题讨论】:

  • 请提供完整错误回溯。
  • cart_item 是一个列表:cart_item = [],因此当您尝试在查询中使用id 时,您会得到AttributeErrorfilter(items.c.cart_item_id==cart_item.id)
  • 您正在使用关联表(“items”),它在 Cart 和 CartItem 之间创建多对多关系。那没有意义。每个 CartItem 将只属于一个 Cart 对象,因此您希望 Cart 和 CartItem 之间存在一对多的关系。
  • @GordThompson 感谢您指出我在多对多关系中的错误。
  • @snakecharmerb 感谢您指出我将 cart_item 分配为列表的错误。

标签: python flask sqlalchemy entity-relationship


【解决方案1】:

谢谢大家的指点。我解决了使用 Cart 和 CartItem 之间的自引用一对多关系查询 cart_item 的问题。

models.py

...
from app import db

class Cart(db.Model):
    __tablename__ = 'cart'
    id = db.Column(db.Integer, primary_key=True)
    user_id = db.Column(db.Integer, db.ForeignKey('user.id'))
    cart_items = db.relationship('CartItem', 
        foreign_keys='CartItem.cart_id', backref='cart', lazy='dynamic', cascade='all, delete-orphan')

    def __repr__(self):
        return '<Cart {}>'.format(self.user_id)


class CartItem(db.Model):
    __tablename__ = 'cart_item'
    id = db.Column(db.Integer, primary_key=True)
    product_id = db.Column(db.Integer, db.ForeignKey('product.id'))
    product = db.relationship('Product', backref=db.backref('cart_item', uselist=False)) 
    cart_id = db.Column(db.Integer, db.ForeignKey('cart.id'))
    # 'cart' property defined in Cart.cart_items via backref.

    def __repr__(self):
        return '<CartItem {}>'.format(self.product_id)
...

routes.py

...
from sqlalchemy.orm import aliased

@cart_blueprint.route('/add_item/<int:product_id>', methods=['GET', 'POST'])
@login_required
def add_item(product_id):
    product = Product.query.get_or_404(product_id)
    cart_id = current_user.id
    cart = Cart.query.get(int(cart_id))
    cart_item = {}
    
    if any(product.id==cart_item.product_id for cart_item in cart.cart_items):
        cart_item = CartItem.query.filter(CartItem.product_id==product_id).\
                                    join(CartItem.cart).\
                                    filter(Cart.id==cart_id).first()
        flash(f'CartItem ID: {cart_item.id} already in cart')
...

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 2012-09-17
    • 2016-06-15
    • 2021-08-31
    • 1970-01-01
    • 2021-08-28
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多