Django throws 'Direct assignment to the forward side of a many-to-many set is prohibited.' error

Souvik Ray picture Souvik Ray · Jun 24, 2018 · Viewed 11.7k times · Source

I have two models in Django Users and Contexts.I have defined the models as below

class User(models.Model):
    userId = models.PositiveIntegerField(null = False)
    pic = models.ImageField(upload_to=getUserImagePath,null=True)
    Email = models.EmailField(null = True)

class Contexts(models.Model):
    context_name = models.CharField(max_length=50)
    context_description = models.TextField()
    context_priority = models.CharField(max_length=1)
    users = models.ManyToManyField(User, related_name='context_users')

Now I get a POST request which contains the below JSON

{
"user" : 12,
"action" : "add",
"context_name": "Network debug",
"context_description" : "Group for debugging network issues",
"context_priority": "L"
}

I want to create a record in the Contexts table.Below is what I am trying to do

from django.shortcuts import render
from django.views.decorators.csrf import csrf_exempt
from django.http import HttpResponse
import json
from .models import *
import json


@csrf_exempt
def context_operation(request):
    if request.method == "POST":
        user_request = json.loads(request.body.decode('utf-8'))
        try:
            if user_request.get("action") == "add":
                conv = Contexts.objects.create(
                    context_name=user_request.get("context_name"),
                    context_description=user_request.get("context_description"),
                    context_priority=user_request.get("context_priority"),
                    users=user_request.get("user")
                )
                conv.save()
        except Exception as e:
            print("Context saving exception", e)
            return HttpResponse(0)
        return HttpResponse(1)

Here I am trying to add a context based on the action field in the JSON request.As you can see, in the Contexts model, the field users has many to many relation with the User model.But when I try to save the values to the Contexts table, I recieve the below error

Context saving exception Direct assignment to the forward side of a many-to-many set is prohibited. Use users.set() instead.

Based on this StackOverflow post, I tried doing something like this:

users=User.objects.add(user_request.get("user"))

But I still receive the same error. What am I doing wrong?

Answer

Daniel Roseman picture Daniel Roseman · Jun 24, 2018

The error should be clear; you cannot assign directly to a many-to-many field. Do it after you create the item.

conv = Contexts.objects.create(
    context_name=user_request.get("context_name"),
    context_description=user_request.get("context_description"),
    context_priority=user_request.get("context_priority"),
)
conv.users.add(user_request.get("user"))

Also note, you don't need to call save() after either create() or adding the m2m values.