Поле модели внешнего ключа Django не обновляется правильно

Итак, у меня возникли проблемы с попыткой обновить поля модели внешнего ключа. Я пытаюсь обновить поле с помощью метода другой модели, но похоже, что он работает некорректно, так как я получаю неверные значения при запуске своего tests.py. Я пытаюсь обновить значение total_purchased. Вот пример того, чего я, по сути, пытаюсь достичь:

Я использую Django 1.6.4

Если вопрос слишком длинный, чтобы резюмировать, можно ли использовать следующие 2 строки? Я делаю это в рамках метода модели класса 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)

person njamaleddine    schedule 23.06.2014    source источник
comment
Можете ли вы поделиться своим кодом / просмотром для корзины?   -  person Jingo    schedule 23.06.2014
comment
@Jingo Добавил часть моего tests.py, где я запускаю код. У меня еще нет настроенных представлений. Спасибо.   -  person njamaleddine    schedule 23.06.2014


Ответы (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.

person Shay    schedule 23.06.2014
comment
Большое спасибо, я на самом деле не осознавал, что неправильно ввел отступ в части item.quantity, а также не понял, что вызывая item.meal, он не вызывает тот же экземпляр. Очень полезный ответ! - person njamaleddine; 23.06.2014