Search code examples
pythondjangodjango-modelsdjango-viewsdjango-templates

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


Hi I have a project in django when I try to runserver the message above is shown this is models.py.

class Display(models.Model) :
    url=models.URLField(unique=True)
    text = models.CharField(max_length=150) 
    
class Display_Data(models.Model) :
    displays = models.ManyToManyField(Display)  
    user= models.ManyToManyField(User)
    choosenum=models.IntegerField()
    puplish_date =models.DateTimeField(default=datetime.now)

and this the views.py:

def submit_operation(request):
 if request.method == 'POST':
    url = request.POST.get('url')
    text = request.POST.get('title')
    choosenum = request.POST.get('CHOOSE')

    if Display.objects.filter(url=url).exists():
        display = Display.objects.get(url=url)
        display_data = Display_Data.objects.create(choosenum=choosenum, user=request.user,                  date_published=datetime.now())
        display_data.displays.add(display)
    else:
        display = Display.objects.create(url=url, text=text)
        display_data = Display_Data.objects.create(choosenum=choosenum, user=request.user,    date_published=datetime.now())
        display_data.displays.add(display)        # ... (إعادة توجيه المستخدم)

    #return redirect('searchpage') 
    return redirect(request.META.get('HTTP_REFERER'))ype herea

and when i try to refer to vidion saved before the message.

I make a site show video from youtube in a frame and asked a user to value the vidio i saved vidio url and when i want from user to again evluate the vidio the mistake apeer


Solution

  • The reason as for why you are seeing this error is that not only displays but user field too has many-to-many relationship.

    You can’t associate [Display_Data] with a [user] until [Display_Data] has been saved.

    reference

    So, just like you are associating your displays model instance, you should associate user instance after you have created and saved display_data model instance.

    Your models.py:

    class Display(models.Model) :
         url=models.URLField(unique=True)
         text = models.CharField(max_length=150) 
    
    class Display_Data(models.Model) :
             displays = models.ManyToManyField(Display)  
             users = models.ManyToManyField(User)
             choosenum = models.IntegerField()
             puplish_date = models.DateTimeField(default=datetime.now) 
    

    since m2m field displays is plural, I made users field plural as well for consistency

    Your views.py:

    def submit_operation(request):
     if request.method == 'POST':
        url = request.POST.get('url')
        text = request.POST.get('title')
        choosenum = request.POST.get('CHOOSE')
    
        try:
            choosenum = int(choosenum)
        except e:
           raise ValueError("couldn't convert choosenum into int")
           # or you can handle the error in a way you like
    
        if Display.objects.filter(url=url).exists():
            display = Display.objects.get(url=url)
            display_data = Display_Data.objects.create(choosenum=choosenum, date_published=datetime.now())
            display_data.displays.add(display)
            display_data.users.add(request.user)
        else:
            display = Display.objects.create(url=url, text=text)
            display_data = Display_Data.objects.create(choosenum=choosenum, date_published=datetime.now())
            display_data.displays.add(display)        # ... (إعادة توجيه المستخدم)
            display_data.users.add(request.user)
    
        #return redirect('searchpage') 
        return redirect(request.META.get('HTTP_REFERER'))ype herea
    

    Also:

    On your models.py your have defined choosenum as an integer field:

    choosenum = models.IntegerField()
    

    But all the data in request.POST is string, so you should convert it to integer:

    choosenum = request.POST.get('CHOOSE')
    
    try:
        choosenum = int(choosenum)
    except e:
        raise ValueError("couldn't convert choosenum into int")
        # or you can handle the error in a way you like