10

I am getting this error when I try to add the current logged in user into another relation as ManyToManyField.

TypeError: Direct assignment to the forward side of a many-to-many set is prohibited. Use user.set() instead.

Here is my code:

Views.py

def add_to_cart(request , item):
    name = item
    size = request.POST.get("size")
    extras = request.POST.get("extras")
    c = Cart(item=name , size=size , extras=extras , user=request.user)
    c.save()
    return render(request , "orders/add_items.html" , {"message":f"{name} added to cart"})

Models.py

class Cart(models.Model):
    item = models.CharField(max_length=64)
    size = models.DecimalField(max_digits=5,decimal_places=2)
    extras = models.CharField(max_length=64 , null=True, blank=True)
    user = models.ManyToManyField(User , related_name="member")

def __str__(self):
    return f"{item} added by {user}"
Alasdair
  • 298,606
  • 55
  • 578
  • 516
haider
  • 103
  • 1
  • 2
  • 9
  • duplicate of https://stackoverflow.com/questions/50015204/direct-assignment-to-the-forward-side-of-a-many-to-many-set-is-prohibited-use-e – Yannic Hamann Sep 13 '18 at 14:01
  • instead of creating instance from model and then saving do the following, new_cart = Cart.objects.create(fieldname=value) new_cart.user.set(). create will let you add or set M2M fields – Bikiran Das Jul 10 '21 at 13:57

1 Answers1

21

You need to save the cart before you can add items to the many-to-many field.

c = Cart(item=name , size=size , extras=extras)
c.save()
c.user.add(request.user)

You could also use set() after saving. Note this will remove any related users not specified in the set (although in this case it's a new list so there aren't any).

c.user.set([request.user]

Finally, are you sure you want a many-to-many field for this? That allows a cart to belong to multiple users. If that's the case, I would name the field users, not user. If you only want one user per cart, then I would use a ForeignKey instead. Your related_name members doesn't make sense either. This is used to get the carts related to a user, so I would expect you to use carts instead.

Alasdair
  • 298,606
  • 55
  • 578
  • 516
  • Is it necessary to use `save()` again after calling `add()` or `set()`? Or is that automatically handled for us? – ArtOfWarfare Oct 29 '20 at 01:24
  • @ArtOfWarfare no you don’t have to call `save()` again. – Alasdair Oct 29 '20 at 08:29
  • I get **TypeError: Field 'id' expected a number but got .** – AnonymousUser May 06 '22 at 04:37
  • "myModel" is example of my model in ***models.py***, and "strName" is the `def __str__(self):` example. In ***models.py***. I can only add one question every 6 months, that's in 5 months now. – AnonymousUser May 07 '22 at 04:28
  • @Alasdair I found the problem. I was adding the wrong model to the `model.field.set(listOfQuerysets)`. My model had a similar name to the one I really had to add. I figured that out when I saw in ***models.py*** that the ManyToManyField had a different model added to it, so I made a list of that model instead in a for loop, and added it instead of the wrong one at `model.field.set(listOfQuerysets)`, and the error went away. – AnonymousUser May 08 '22 at 05:12
  • Glad you figured it out – Alasdair May 09 '22 at 07:50