【问题标题】:Can't get ModelForm ChoiceField return as string - Cannot assign "'5'": "Reclamacoes.uf" must be a "Estados" instance无法以字符串形式返回 ModelForm ChoiceField - 无法分配“'5'”:“Reclamacoes.uf”必须是“Estados”实例
【发布时间】:2025-12-28 20:50:06
【问题描述】:

此表单从数据库中的模型 Estados、Cidades、Categorias 和 Status 中获取条目,以显示在 ChoiceFields 中。其他字段是 CharFields、EmailFields 和 PhoneNumberField(来自 this lib)。

按正确数据的提交按钮后,我收到以下错误:“无法分配“'5'”:“Reclamacoes.uf”必须是“Estados”实例。”尝试了几种不同的小部件和表单元素来尝试将此输入作为字符串(包括 forms.Select),但它们没有达到我正在寻找的目的。

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})

【问题讨论】:

    标签: python mysql django modelform


    【解决方案1】:

    错误表示您试图在Reclamacoes 模型中分配一个字符串或整数5 作为外键,这将不起作用。您不能将字符串或整数分配给外键字段。它必须是您所指的模型的一个实例。

    您可能需要做的是提取Estados 模型的ID,在本例中为5

    所以在if form_rec.is_valid(): 块中的views.py 中更改保存方法:

    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()
    

    【讨论】:

    • 我之前试过这个解决方案,但也没有用,返回同样的错误
    • 在这行estado = Estado.objects.get(id=estado_id)之后添加一个打印语句。喜欢print(estado)print(type(estado))。然后检查控制台输出的内容。
    • 我从头开始重写了代码,现在使用了不同的方法。 jQuery + AJAX 来实现我一直在寻找的目的。但是谢谢老兄,你的回答让我走上了正确的道路!