Search code examples
djangodjango-signals

ValueError: needs to have a value for field "cart" before this many-to-many relationship can be used


I'm facing the problem with the following code:

class Cart(models.Model):
    user = models.ForeignKey(settings.AUTH_USER_MODEL, null=True, blank=True)
    items = models.ManyToManyField(CC, blank=True)
    total = models.DecimalField(max_digits=10, decimal_places=2, default=0.00)

    def __str__(self):
        return self.user.username


@receiver(pre_save, sender=Cart)
def cart_update_total(sender, instance, *args, **kwargs):
    total = Decimal(0.00)
    for item in instance.items.all():
        total += item.price
    instance.total = total


@receiver(user_activated)
def user_created(sender, user, request, **kwargs):
    cart, created = Cart.objects.get_or_create(user=user)

So basically I create a Cart model for user who activates account. But also I'm using pre_save signal for Cart where I calculate total price for products in cart. Therefore pre_save function tries to access fields of object which has not been saved yet. Can you guys advise me how can I modify this logic to get it work correctly?


Solution

  • I don't think pre_save or post_save is able to do that because the m2m fields won't be accessible before the actual Cart object exists.

    You could access the items field when people add/remove items from the existing cart, by using m2m_changed signal. So every time user updates the cart, this method gets triggered and update the total.

    I don't think it makes much sense to calculate total when cart is created, because, well, if you don't have a cart, how can you add items to it? I would separate these two processes to let user creates a cart first then do the shopping, but it's up to your business logic to make the decision.