【问题标题】:Django foreign key's model field not updating correctlyDjango 外键的模型字段没有正确更新
【发布时间】:2014-08-13 15:45:32
【问题描述】:

所以我在尝试更新外键模型的字段时遇到了麻烦。我正在尝试通过另一个模型的方法更新该字段,但它似乎无法正常工作,因为我在运行我的 tests.py 时得到了不正确的值。我正在尝试更新“total_purchased”的值。下面是我基本上想要完成的一个例子:

我正在使用 Django 1.6.4

如果问题太长无法概括,是否允许以下​​两行?我是在 django 类模型方法中做的:

Ex: Model.ForeignKeyModel.field = some_value
    Model.ForeignKeyModel.save()

有以下3种型号:

class Meal (models.Model):
    name = models.CharField(max_length=255)
    total_purchased = models.IntegerField(default=0, validators=[MaxValueValidator(capacity)])
    capacity = models.IntegerField(default=500)

class Item (models.Model):
    cart = models.ForeignKey(Cart)
    meal = models.ForeignKey(Meal)
    quantity = models.IntegerField(validators=[MinValueValidator(0)], default=0)

class Cart (models.Model):
    delivery = models.ForeignKey(DeliveryInfo)
    subscription = models.BooleanField(default=False)
    customer = models.ForeignKey(User)

    def add(self, meal, quantity):
        """ Dual Add/Remove from cart method, (quantity replaces current quantity) """
        item = Item.objects.get_or_create(cart=self, meal=meal)[0]
        remaining_capacity = item.meal.capacity - item.meal.total_purchased

        # Meal exists on our cart, so proceed with adding or removing
        if quantity <= remaining_capacity:

            if quantity == 0:
                # Add back whatever quantity the user didn't buy
                item.meal.total_purchased = 0
                item.meal.save()

                # Remove entire item from cart (quantity = 0)
                item.delete()

            elif quantity == item.quantity:
                # Do nothing if cart quantity equals current quantity
                pass

            else:
                if quantity < item.quantity:
                    # Decrement total purchased
                    item.meal.total_purchased -= (item.quantity - quantity)
                    item.meal.save()

                else:
                    # Increment total_purchased by the quantity we're adding to the cart
                    item.meal.total_purchased += (quantity - item.quantity)
                    item.meal.save()

            # Update the Cart
            item.quantity = quantity
            item.save()

            remaining_capacity = item.meal.capacity - item.meal.total_purchased

    else:
        exceeded = abs(remaining_capacity - quantity)
        raise ValidationError("Your cart exceeds the total remaining quantity by {0}!".format(exceeded))

更新后它第一次工作,但似乎忽略了下一个添加到购物车方法调用,我最终在我的 tests.py 中得到以下内容: self.assertEqual(item.total_purchased, 2) AssertionError: 1 != 2

我不确定是因为在 tests.py 中发生了购物车更新,还是我以某种方式错误地保存了数据。任何帮助将不胜感激。

这里的要求是我的tests.py,我从中运行测试:

customer = User.objects.filter(pk=1)[0]
delivery_info = DeliveryInfo.objects.filter(owner=customer)[0]
cart_order = CartOrder.objects.create(owner=customer, delivery=delivery_info, subscription=False)

# Query the meal_items
curry_item = Meal.objects.get(pk=1)
burger_item = Meal.objects.get(pk=2)

# Add some meal items to our cart, the cart_order add method creates Items
cart_order.add(curry_item, 2)
cart_order.add(burger_item, 1)

self.assertEqual(burger_item.total_purchased, 1)

# Removing one item from the cart
cart_order.add(curry_item, 1)

# Doing nothing to the cart
cart_order.add(curry_item, 1)

** 这是无法正确更新值的地方:**

# Adding an item to the cart
cart_order.add(burger_item, 2)
self.assertEqual(burger_item.total_purchased, 2)

【问题讨论】:

  • 你能分享你相应的购物车代码/视图吗?
  • @Jingo 添加了我的tests.py 的部分,我正在运行代码。我还没有设置任何视图。谢谢。

标签: python django django-models foreign-key-relationship cart


【解决方案1】:

发生这种情况是因为您使用的模型实例未更新。
第一次调用get_or_create 它创建Item 并使用meal=meal 中的Meal,而第二次调用Item 并且不使用Meal 的相同实例。

由于您已经将meal 的实例作为参数,您可以将item.meal 替换为meal,您应该会看到您想要的结果。或者,您可以在添加后重新加载burger_item 或任何餐点。

您确实应该考虑使用 F() 表达式来执行增量,因为它们仅在数据库端执行并且可以帮助防止竞争条件。请注意,使用 F() 表达式需要您重新加载 Meal 才能看到它的新值。

在旁注中,请注意

# Update the Cart
item.quantity = quantity
item.save()

quantity == 0 和您删除Item 的情况下被调用,因为这将重新创建Item

【讨论】:

  • 非常感谢,我实际上没有意识到我错误地缩进了 item.quantity 部分,也没有意识到通过调用 item.meal 它不会调用相同的实例。很有帮助的答案!
猜你喜欢
  • 2011-11-16
  • 2017-06-03
  • 2015-10-14
  • 2020-09-09
  • 1970-01-01
  • 1970-01-01
  • 2021-10-11
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多