Django ManyToMany relationship with ModelMultipleChoice Error

I am fairly new to Django. So trying to use inbuilt functionalities instead of overriding the functions. I have established ManyToMany relationship between user and service.

Means a user can have many services and a service can be obtained by many users. (Not sure if I am correct)

Following are my models

Userdata

from django.db import models
from django.contrib.auth.models import User
from services.models import Services

class Userdata(models.Model):
    username=models.OneToOneField(User,on_delete=models.CASCADE)
    tel=models.CharField(max_length=10,unique=True)
    address=models.CharField(max_length=100,null=True,blank=True)
    city=models.CharField(max_length=10,null=True,blank=True)
    zipcode=models.CharField(max_length=6,null=True,blank=True)
    services=models.ManyToManyField(Services,through='dashuser.UpcomingUserServices')

Services

from django.db import models

class Services(models.Model):
    sname=models.CharField(max_length=20)
    scost=models.IntegerField()

    def __str__(self):
        return self.sname

UpcomingUserService

from django.db import models
from services.models import Services
from log.models import Userdata

class UpcomingUserServices(models.Model):
    userdata=models.ForeignKey(Userdata,on_delete=models.CASCADE)
    service=models.ForeignKey(Services,on_delete=models.CASCADE)
    name=models.CharField(max_length=20)
    phone=models.CharField(max_length=10)
    date=models.DateField()
    address=models.CharField(max_length=100)
    zipcode=models.IntegerField()
    remarks=models.CharField(max_length=100,null=True,blank=True)

ServiceForm

from django import forms
from .models import UpcomingUserServices

class ServiceForm(forms.ModelForm):
    service=forms.ModelMultipleChoiceField(Services.objects.all(),widget=forms.CheckboxSelectMultiple())

    class Meta:
        model=UpcomingUserServices
        exclude=['userdata']

view

def book(request):
    if request.method=='POST':
        serlist=[]
        f=ServiceForm(request.POST)
        if f.is_valid():
            s=f.save(commit=False)
            u=request.user
            u1=Userdata.objects.get(username_id=u.id)
            s.userdata_id=u1.id
            f.save()
            f.save_m2m()
            return HttpResponse('Done')
        else:
            return render(request,'ns.html',{'f':f})
    else:
        u=request.user
        u1=Userdata.objects.get(username_id=u.id)
        i={
            'name':u.first_name+" "+u.last_name,
            'phone':u1.tel,
            'email':u.email,
            'address':u1.address,
            'zipcode':u1.zipcode
        }
        f = ServiceForm(initial=i)
        return render(request,'ns.html',{'f':f})
# ns.html is where the form is rendered

When the form is submitted, I get following error

ValueError at /user/book
Cannot assign "<QuerySet [<Services: Lawn Mowing>, <Services: Lawn Fertilization>]>": "UpcomingUserServices.service" must be a "Services" instance

(/user/book is view's URL)

TrackBack:

Traceback:

File "F:\My Projects\login\venv\lib\site-packages\django\core\handlers\exception.py" in inner
  34.             response = get_response(request)

File "F:\My Projects\login\venv\lib\site-packages\django\core\handlers\base.py" in _get_response
  126.                 response = self.process_exception_by_middleware(e, request)

File "F:\My Projects\login\venv\lib\site-packages\django\core\handlers\base.py" in _get_response
  124.                 response = wrapped_callback(request, *callback_args, **callback_kwargs)

File "F:\My Projects\login\venv\lib\site-packages\django\contrib\auth\decorators.py" in _wrapped_view
  21.                 return view_func(request, *args, **kwargs)

File "F:\My Projects\login\dashuser\views.py" in book
  63.         if f.is_valid():

File "F:\My Projects\login\venv\lib\site-packages\django\forms\forms.py" in is_valid
  185.         return self.is_bound and not self.errors

File "F:\My Projects\login\venv\lib\site-packages\django\forms\forms.py" in errors
  180.             self.full_clean()

File "F:\My Projects\login\venv\lib\site-packages\django\forms\forms.py" in full_clean
  383.         self._post_clean()

File "F:\My Projects\login\venv\lib\site-packages\django\forms\models.py" in _post_clean
  398.             self.instance = construct_instance(self, self.instance, opts.fields, opts.exclude)

File "F:\My Projects\login\venv\lib\site-packages\django\forms\models.py" in construct_instance
  60.             f.save_form_data(instance, cleaned_data[f.name])

File "F:\My Projects\login\venv\lib\site-packages\django\db\models\fields\__init__.py" in save_form_data
  854.         setattr(instance, self.name, data)

File "F:\My Projects\login\venv\lib\site-packages\django\db\models\fields\related_descriptors.py" in __set__
  210.                     self.field.remote_field.model._meta.object_name,

Exception Type: ValueError at /user/book
Exception Value: Cannot assign "<QuerySet [<Services: Lawn Mowing>, <Services: Lawn Fertilization>]>": "UpcomingUserServices.service" must be a "Services" instance.

1 answer

  • answered 2019-01-11 08:03 Yongjin Jo

    You use UpcomingUserServices model by intermediate model. So UpcomingUserServices model must take one user and one service. But your ServiceForm took multiple services by forms.ModelMultipleChoiceField.

    I know what you're trying to implement. But that's not correct.

    You are using intermediate table. So check intermediary many to many and similar case question