Can't get ModelForm ChoiceField return as string - Cannot assign "'5'": "Reclamacoes.uf" must be a "Estados" instance

Viewed 106

This form gets entries from models Estados, Cidades, Categorias and Status from the database, to be displayed in ChoiceFields. The other fields are CharFields, EmailFields and a PhoneNumberField (from this lib).

After pressing the submit button with proper data, I get the following error: "Cannot assign "'5'": "Reclamacoes.uf" must be a "Estados" instance." Tried several different widgets and form elements to try and get this input as string (including forms.Select), but they don't fulfill the purpose I'm looking for.

models.py

from django.db import models
from phonenumber_field.modelfields import PhoneNumberField

class Estados(models.Model):
    nome = models.CharField(("nome"), max_length=50)
    unidade = models.CharField(("unidade"), max_length=2)
    disponibilidade = models.BooleanField(("disponibilidade"), default=False)

class Cidades(models.Model):
    nome = models.CharField(("nome"), max_length=50)
    uf = models.ForeignKey("Estados", on_delete=models.CASCADE)
    disponibilidade = models.BooleanField(("disponibilidade"), default=False)

class Categorias(models.Model):
    tipo = models.CharField(("tipo"), max_length=50)
    disponibilidade = models.BooleanField(("disponibilidade"), default=False)
    nome = models.CharField(("nome"), max_length=50)

class Status(models.Model):
    status = models.CharField(("status"), max_length=50)

class Reclamacoes(models.Model):
    uf = models.ForeignKey("Estados", on_delete=models.CASCADE)
    cidade = models.ForeignKey("Cidades", on_delete=models.CASCADE)
    categoria = models.ForeignKey("Categorias", on_delete=models.CASCADE)
    autor = models.CharField(("autor"), max_length=50)
    email = models.EmailField(("email"), max_length=254)
    telefone = PhoneNumberField(null=False, blank=False, unique=False)
    reclamacao = models.CharField(("reclamacao"), max_length=50000)
    status = models.ForeignKey("Status", on_delete=models.CASCADE)

forms.py

from django import forms
from django.db.models import fields
from phonenumber_field.formfields import PhoneNumberField
from .models import Estados, Cidades, Categorias, Status, Reclamacoes
from django.core.exceptions import ValidationError


class FormReclamacao(forms.ModelForm):
    
    uf = forms.ChoiceField(choices=[(item.id, item.nome) for item in Estados.objects.filter(disponibilidade=1).order_by('unidade')])
    cidade = forms.ChoiceField(choices=[(item.id, item.nome) for item in Cidades.objects.filter(disponibilidade=1).order_by('nome')])
    categoria = forms.ChoiceField(choices=[(item.id, item.nome) for item in Categorias.objects.filter(disponibilidade=1)])
    status = forms.ChoiceField(choices=[(item.id, item.status) for item in Status.objects.all()])
    class Meta:
        model = Reclamacoes
        fields = ("__all__")

views.py

def reclamacoes(request):
    
    if request.method == 'POST':
        form_rec = FormReclamacao(request.POST)

        if form_rec.is_valid():
            r = form_rec.save()

            return HttpResponseRedirect('/cad')
            
    else:
        form_rec = FormReclamacao()

    return render(request, 'reclamacoes.html', {'form':form_rec})
1 Answers

The error says that you are trying to either assign a string or integer 5 as a foreign key in the Reclamacoes model, which will not work. You cannot assign a string or integer to a foreign key field. It has to be an instance of the model that you are referring to.

What you may need to do is extract the id of the Estados model, which in this case is 5.

So in your views.py in the if form_rec.is_valid(): block alter the save method:

r = form_rec.save(commit=False)

estado_id = form.cleaned_data["uf"]

# make sure that estado_id is an int and not a string

estado = Estado.objects.get(id=estado_id)
r.uf = estado

#... do the same for all foreign keys ...

r.save()
Related