Cannot assign, Must be an instance Error

Hello everyone I am keep getting this error and I don’t understand why, I want to send an email with django when user fills out the form and I want to select recipents with the form, I made a model form and when I try to select recipents I get the error. Here is my code:

models.py:

class State(models.Model):
    profile = models.ForeignKey(Profile, on_delete=models.CASCADE)
    country = models.CharField(max_length=100)
    capital = models.CharField(max_length=100)
    president = models.ManyToManyField(President)
    city = models.ManyToManyField(Cities)
    date = models.DateTimeField()
    slug = models.SlugField(unique=True)

    def save(self, *args, **kwargs):
        self.slug = slugify(self.country)
        super(State, self).save(*args, **kwargs)

    def __str__(self):
        return self.country
    
    def get_absolute_url(self):
        return reverse('mailapp2:details', args=[self.slug])
    

and my profile model has user object which has OneToOne relation with the django’s User model,

forms.py:

class StateForm(forms.ModelForm):
    city = forms.ModelMultipleChoiceField(queryset=Cities.objects.all(), required=True)
    president= forms.ModelMultipleChoiceField(queryset=President.objects.all(), required=True)
    profile = forms.ModelMultipleChoiceField(queryset=Profile.objects.all(), required=True)
    class Meta:
        model = State
        fields = ('country','capital','city', 'date', 'president','profile')
        widgets = {
            'country':forms.TextInput(attrs={"placeholder":"Country", "required":"True", "style":"width:40%;"}),
            'capital':forms.TextInput(attrs={"placeholder":"Capital", "required":"True", "style":"width:40%;"}),
            'city':forms.CheckboxSelectMultiple(attrs={"placeholder":"choose a city"}),
            'date':forms.DateTimeInput(attrs={"type":"text", "onfocus":"(this.type='datetime-local')","placeholder":"Date","id":"date"}),
            'president':forms.CheckboxSelectMultiple(attrs={"placeholder":"President","class":"katılımcıselect"}),
            'profile':forms.CheckboxSelectMultiple(attrs={"placeholder":"Recipents","class":"recipentselect"}),
        }
        labels = {
            'country':'country',
            'capital':'capital',
            'city':'city',
            'date':'date',
            'president':'president',
            'profile':'profile'
        }

(this is a dummy project to understand how django’s email backend works so the object’s names are pointless)

and my views.py:

def addState(request):
    if request.method == 'POST':
        form = StateForm(data=request.POST)
        if form.is_valid():
            date = form.cleaned_data['date']
            city= form.cleaned_data['city']
            profile = form.cleaned_data['profile']
            new_state = form.save(commit=False)
            user_profile = Profile.objects.get(user=request.user)
            new_state.profile = user_profile
            new_state.save()
            form.save_m2m()

            template = render_to_string('mailapp2/email.html', {
                                            'name':request.user.username,
                                            'date':date,
                                            'city':city,
                                            'profile':profile
                                            })
            plain_message = strip_tags(template)

            email = EmailMessage(
                'State Notification',
                plain_message,
                settings.EMAIL_HOST_USER,
                [profile.user.email], 
            )
            email.fail_silently=False
            email.send()            

            return redirect('http://127.0.0.1:8000/')
        else:
            print(form.errors)
    else:
        form = StateForm(data=request.GET)
    return render(request, 'mailapp2/add_state.html',{
        'form':form
    })

I cannot see where is my problem, thank you from now :slight_smile:
PS. I translated its language so there may be little spelling errors but it is working in main project, this is why all objects are silly

This is not the syntax for that. It should be email.send(fail_silently=False)

See the docs at Sending email | Django documentation | Django

1 Like
        email.fail_silently=False
        email.send()

this was working until I add

profile = form.cleaned_data[‘profile’]

it is saying it must be Profile instance but I am trying to render Profile instance

email = EmailMessage(
Toplantı Bildirimi’,
plain_message,
settings.EMAIL_HOST_USER,
devlet.profile.user.email]

I am sorry I forgot the show the actual error code.

ValueError at /addState/
Cannot assign "<QuerySet [<Profile: profile1>, <Profile: profile2>, <Profile: profile3>]>": "State.profile" must be a "Profile" instance.

Please post the complete traceback.

there might be language difference in the objects that I can not see in the traceback

Environment:


Request Method: POST
Request URL: http://127.0.0.1:8000/devlet_ekle/

Django Version: 4.2.6
Python Version: 3.12.1
Installed Applications:
['mailapp2',
 'django.contrib.admin',
 'django.contrib.auth',
 'django.contrib.contenttypes',
 'django.contrib.sessions',
 'django.contrib.messages',
 'django.contrib.staticfiles']
Installed Middleware:
['django.middleware.security.SecurityMiddleware',
 'django.contrib.sessions.middleware.SessionMiddleware',
 'django.middleware.common.CommonMiddleware',
 'django.middleware.csrf.CsrfViewMiddleware',
 'django.contrib.auth.middleware.AuthenticationMiddleware',
 'django.contrib.messages.middleware.MessageMiddleware',
 'django.middleware.clickjacking.XFrameOptionsMiddleware']



Traceback (most recent call last):
  File "C:\Users\TP054591\AppData\Local\Programs\Python\Python312\Lib\site-packages\django\core\handlers\exception.py", line 55, in inner
    response = get_response(request)
               ^^^^^^^^^^^^^^^^^^^^^
  File "C:\Users\TP054591\AppData\Local\Programs\Python\Python312\Lib\site-packages\django\core\handlers\base.py", line 197, in _get_response
    response = wrapped_callback(request, *callback_args, **callback_kwargs)
               ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
  File "C:\Users\TP054591\Desktop\Taha Polat Projeler\AralıkProjeleri\211223Proje\mailapp2\views.py", line 80, in devlet_ekle
    if form.is_valid():
       ^^^^^^^^^^^^^^^
  File "C:\Users\TP054591\AppData\Local\Programs\Python\Python312\Lib\site-packages\django\forms\forms.py", line 201, in is_valid
    return self.is_bound and not self.errors
                                 ^^^^^^^^^^^
  File "C:\Users\TP054591\AppData\Local\Programs\Python\Python312\Lib\site-packages\django\forms\forms.py", line 196, in errors
    self.full_clean()
    ^^^^^^^^^^^^^^^^^
  File "C:\Users\TP054591\AppData\Local\Programs\Python\Python312\Lib\site-packages\django\forms\forms.py", line 435, in full_clean
    self._post_clean()
    ^^^^^^^^^^^^^^^^^^
  File "C:\Users\TP054591\AppData\Local\Programs\Python\Python312\Lib\site-packages\django\forms\models.py", line 479, in _post_clean
    self.instance = construct_instance(
                    
  File "C:\Users\TP054591\AppData\Local\Programs\Python\Python312\Lib\site-packages\django\forms\models.py", line 83, in construct_instance
    f.save_form_data(instance, cleaned_data[f.name])
    ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
  File "C:\Users\TP054591\AppData\Local\Programs\Python\Python312\Lib\site-packages\django\db\models\fields\__init__.py", line 1035, in save_form_data
    setattr(instance, self.name, data)
    ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
  File "C:\Users\TP054591\AppData\Local\Programs\Python\Python312\Lib\site-packages\django\db\models\fields\related_descriptors.py", line 266, in __set__
    raise ValueError(
    ^

Exception Type: ValueError at /devlet_ekle/
Exception Value: Cannot assign "<QuerySet [<Profile: profile1>, <Profile: profile2>, <Profile: profile3>]>": "State.profile" must be a "Profile" instance.

So, notice that the error in your code is occurring here:

You’re binding the data to the form here:

which means you’re submitting something in the form that can’t be bound to the model.

Further down in the traceback it shows:

telling us which field is causing the problem.

Your definition of profile in State is this:

This means that the profile field contains a reference to one instance of Profile.

However, you have your form defined as:

Which would allow the user to select multiple instances of Profile - but that’s not valid for your model.

Your form’s profile field would need to be a ModelChoiceField, not a ModelMultipleChoiceField.

1 Like

so if I change

profile = models.ForeignKey(Profile, on_delete=models.CASCADE)

by:

profile = models.ManyToManyField(Profile, on_delete=models.CASCADE)

then can I use ModelMultipleChoiceField for selecting multiple profiles to send mail?

Yes, that would work.

Additionally, see the notes regarding save with commit=False and using the save_m2m method in the docs at Creating forms from models | Django documentation | Django

1 Like