Trying to Resolve a "Direct assignment to the forward side of a many-to-many set is prohibited. Use category.set() instead." error

I am a student working on a project for my coding bootcamp and I'm having to resolve an issue with a many to many field. The theme of the project is app that lets users post screenshots from various video game and label them bases on category, 3rd party editing and capture tools.

I'm trying to write code for POST and PUT requests that will allow a user to select several objects in a React.js form.

I'd also try and test whatever solution I get in postman. I've added fixtures into my database and the fixtures work, but when attempting to test by using raw JSON in the body like this:

`

         "category": 1,

or

 "category": [
            1,
            2,
            3
        ]

` I get the error show in the title of this post.

I'm using Python 3.9.10 and Django 4.14.

my model looks like this:

screenshot.py `

from django.db import models
from .archer import Archer
from .editingtool import EditingTool
from .capturetool import CaptureTool
from .category import Category

class Screenshot(models.Model):
    archer = models.ForeignKey (Archer, on_delete=models.CASCADE)
    image = models.CharField(max_length=255, null=True)
    content = models.TextField()
    captureTool = models.ForeignKey (CaptureTool, on_delete=models.CASCADE)
    editingTool = models.ForeignKey (EditingTool, on_delete=models.CASCADE)
    category = models.ManyToManyField ('Category', through='ScreenshotCategory')
    timestamp = models.DateField(auto_now_add=True)

`

category.py `

from django.db import models

class Category(models.Model):
    description = models.CharField(max_length=255)

**screenshotcategory.py **

from django.db import models
from .screenshot import Screenshot

class ScreenshotCategory(models.Model):
    screenshot = models.ForeignKey (Screenshot, on_delete=models.CASCADE)
    category = models.ForeignKey ('Category', on_delete=models.CASCADE, related_name="screenshot_category")

`

and my view looks like this

screenshot.py `

def create(self, request):
        """ Handle a POST request for a Screenshot item """
        
        archer  = Archer.objects.get(user=request.auth.user)
        captureTool = CaptureTool.objects.get(pk=request.data["captureTool"])
        editingTool = EditingTool.objects.get(pk=request.data["editingTool"])
        category = Category.objects.get(pk=request.data["category"])
        
        new_screenshot = Screenshot.objects.create(
            archer=archer,
            image=request.data["image"],
            content=request.data["content"],
            captureTool=captureTool,
            editingTool=editingTool,
            category = category,
            timestamp=request.data["timestamp"]
            )
        serializer = ScreenshotSerializer(new_screenshot)
        return Response(serializer.data, status=status.HTTP_201_CREATED)

    def update(self, request, pk):
        """ Handles a PUT request for a Screenshot item """
        
        captureTool = CaptureTool.objects.get(pk=request.data["captureTool"])
        editingTool = EditingTool.objects.get(pk=request.data["editingTool"])
        category = Category.objects.get(pk=request.data["category"])

        editing_screenshot = Screenshot.objects.get(pk=pk)
        editing_screenshot.image = request.data["image"]
        editing_screenshot.content = request.data["content"]
        editing_screenshot.captureTool = captureTool
        editing_screenshot.editingTool = editingTool
        editing_screenshot.category =category
        editing_screenshot.save()

        return Response(None, status=status.HTTP_204_NO_CONTENT)

`

I've tried adding using the code as it to no success. I was expecting that when testing in post man to get back an object that looks like this

`

"id": 6,
        "archer": 1,
        "image": "https://url.png",
        "content": "content",
        "captureTool": 1,
        "editingTool": 1,
        "category": [
            1,
            2,
            3
        ],
        "timestamp": "2020-03-12"

` but instead i get an error.

I think your solution will be something like this:

screen_shot = ScreenshotCategory.objects.get(id=pk)
Category = Category.objects.get(id = orden_id)
screen_shot.category.add(category)

hope it helps

You need to set all objects of Category model in Screenshot model which contain many-to-many field of Category model

basically many-to-many field have list of object, not single object so, you need to add all objects in many-to-many field. like this

here i put code for create method.

def create(self, request):
        """ Handle a POST request for a Screenshot item """
        
        archer  = Archer.objects.get(user=request.auth.user)
        captureTool = CaptureTool.objects.get(pk=request.data["captureTool"])
        editingTool = EditingTool.objects.get(pk=request.data["editingTool"])
        
        new_screenshot = Screenshot.objects.create(
            archer=archer,
            image=request.data["image"],
            content=request.data["content"],
            captureTool=captureTool,
            editingTool=editingTool,
            timestamp=request.data["timestamp"]
        ).save()

        for i in request.data["category"]:
            cate = Category.objects.get(id=i)
            new_screenshot.category.add(cate)

        serializer = ScreenshotSerializer(new_screenshot)
        return Response(serializer.data, status=status.HTTP_201_CREATED)
Back to Top