首页 > 解决方案 > ValueError:无法分配对象必须是实例

问题描述

我一直在尝试注册一个ClienteNatural,它有两个外键,一个是Correo,另一个是Lugar。在数据库中进行查询以将Correo对象传递给ClienteNatural时,如果有人可以帮助我,我会收到此错误。谢谢你。暂时我把一个固定值给Lugar只是为了测试,然后我会让它动态,但是我分配给fk_lugar的那个Lugar对象不会产生错误,只是fk_correo

错误:

*** ValueError:无法分配“'Correo object (22)'”:“ClienteNatural.fk_correo”必须是“Correo”实例。

模型.py

class ClienteNatural(models.Model):
rif = models.CharField(primary_key=True, max_length=12)
carnet_id = models.IntegerField(blank=True, null=True)
complemento_direccion = models.CharField(max_length=25)
puntos_disponibles = models.IntegerField(blank=True, null=True)
cedula = models.CharField(max_length=12)
primer_nombre = models.CharField(max_length=12)
segundo_nombre = models.CharField(max_length=12, blank=True, null=True)
primer_apellido = models.CharField(max_length=12)
segundo_apellido = models.CharField(max_length=12)
fk_lugar = models.ForeignKey('Lugar', db_column='fk_lugar', on_delete=models.CASCADE)
fk_correo = models.ForeignKey('Correo', db_column='fk_correo', on_delete=models.CASCADE)

class Meta:
    managed = False
    db_table = 'cliente_natural'

class Correo(models.Model):
codigo = models.AutoField(primary_key=True)
usuario = models.CharField(unique=True, max_length=30)

class Meta:
    managed = False
    db_table = 'correo'

class Lugar(models.Model):
codigo = models.AutoField(primary_key=True)
nombre = models.CharField(max_length=50)
tipo = models.CharField(max_length=50)
fk_lugar = models.ForeignKey('self', models.DO_NOTHING, db_column='fk_lugar', blank=True, null=True)

class Meta:
    managed = False
    db_table = 'lugar'

表格.py

class Cliente_Natural_Form(forms.ModelForm):
rif = forms.CharField(max_length=12, required=True)
carnet_id = forms.IntegerField
complemento_direccion = forms.CharField(max_length=25, required=True,
                                        validators=[RegexValidator(regex='^[a-zA-Z]*$',
                                                                   message='El apellido solo debe contener letras',
                                                                   code='invalid_last_name')])
puntos_disponibles = forms.IntegerField
cedula = forms.CharField(max_length=12, required=True,
                         validators=[RegexValidator(regex='^[0-9]*$',
                                                    message='La cedula debe contener solo numeros',
                                                    code='invalid_cedula')])
primer_nombre = forms.CharField(max_length=12, required=True,
                                validators=[RegexValidator(regex='^[a-zA-Z]*$',
                                                           message='El nombre solo debe contener letras',
                                                           code='invalid_primer_nombre')])
segundo_nombre = forms.CharField(max_length=12, required=False,
                                 validators=[RegexValidator(regex='^[a-zA-Z]*$',
                                                            message='El segundo nombre solo debe contener letras',
                                                            code='invalid_segundo_nombre')])
primer_apellido = forms.CharField(max_length=12, required=True,
                                  validators=[RegexValidator(regex='^[a-zA-Z]*$',
                                                             message='El primer apellido solo debe contener letras',
                                                             code='invalid_primer_apellido')])
segundo_apellido = forms.CharField(max_length=12, required=True,
                                   validators=[RegexValidator(regex='^[a-zA-Z]*$',
                                                              message='El segundo apellido solo debe contener letras',
                                                              code='invalid_segundo_apellido')])
fk_lugar = forms.IntegerField(widget=forms.HiddenInput())
fk_correo = forms.CharField(widget=forms.HiddenInput())

class Meta:
    model = ClienteNatural
    fields = ('rif', 'carnet_id', 'complemento_direccion', 'puntos_disponibles', 'cedula', 'primer_nombre',
              'segundo_nombre', 'primer_apellido', 'segundo_apellido', 'fk_lugar', 'fk_correo')


class Correo_Form(forms.ModelForm):
usuario = forms.CharField(max_length=30, required=True)

class Meta:
    model = Correo
    fields = ('usuario',)

class Lugar_Form(forms.ModelForm):
nombre = forms.CharField(max_length=50, required=True)
tipo = forms.CharField(max_length=50, required=True)
fk_lugar = forms.IntegerField(required=False)

class Meta:
    model = Lugar
    fields = ('nombre', 'tipo', 'fk_lugar')

视图.py

def registroClienteNatural(request):
if request.method == "POST":
    formLugar = forms.Lugar_Form(request.POST)
    formCorreo = forms.Correo_Form(request.POST)
    formClienteNatural = forms.Cliente_Natural_Form(request.POST)
    dataCorreo = {'usuario': request.POST.get('usuario')}
    formCorreo = forms.Correo_Form(dataCorreo)
    if formCorreo.is_valid():
        try:
            formCorreo.save()
        except:
            pass
    dataCliente = {'rif': request.POST.get('rif'),
                   'carnet_id': request.POST.get('carnet_id'),
                   'complemento_direccion': request.POST.get('complemento_direccion'),
                   'puntos_disponibles': request.POST.get('puntos_disponibles'),
                   'cedula': request.POST.get('cedula'),
                   'primer_nombre': request.POST.get('primer_nombre'),
                   'segundo_nombre': request.POST.get('segundo_nombre'),
                   'primer_apellido': request.POST.get('primer_apellido'),
                   'segundo_apellido': request.POST.get('segundo_apellido'),
                   'fk_lugar': Lugar.objects.get(codigo=5),
                   'fk_correo': Correo.objects.get(usuario=request.POST.get('usuario'))
                   }
    formClienteNatural = forms.Cliente_Natural_Form(dataCliente)
    if formClienteNatural.is_valid():
        try:
            formClienteNatural.save()
        except:
            pass
else:
    formUsuario = forms.Usuario_Form()
    formClienteNatural = forms.Cliente_Natural_Form()
    formTelefono = forms.Telefono_Form()
    formCorreo = forms.Correo_Form()
    formLugar = forms.Lugar_Form()
return render(request, 'Home/registroUsuario.html', {'formUsuario': formUsuario,
                                                     'formClienteNatural': formClienteNatural,
                                                     'formTelefono': formTelefono,
                                                     'formCorreo': formCorreo,
                                                     'formLugar': formLugar})

标签: pythondjangoforeign-keys

解决方案


你的问题在于你的形式。这应该有效:

fk_lugar = forms.IntegerField(widget=forms.HiddenInput())
fk_correo = forms.IntegerField(widget=forms.HiddenInput())

这里的问题是,当您说fk_correois a时CharField,django 的某处将对象转换为字符串。请注意,在您的错误消息中,三引号表示 ValueError 是因为您传递的是字符串而不是对象:

*** ValueError: Cannot assign "'Correo object (22)'": "ClienteNatural.fk_correo" must be a "Correo" instance.

当您使用IntegerFieldthen django 时会发现,当您传递一个对象时,您会隐式传递主键。这就是为什么在fk_lugar工作但不是fk_correo


推荐阅读