You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

Django报错:无法为Results.patient分配字符串,需为Patient实例

问题:给结果表单关联患者时出现类型错误

报错信息

Cannot assign "'75f37671bac8'": "Results.patient" must be a "Patient" instance.

给结果表单添加患者时触发上述报错,试过多种方法都无法解决,求各位帮忙,谢谢。

Models.py

class Patient(models.Model):
    uniqueId = models.CharField(null=True, blank=True, max_length=100)
    slug = models.SlugField(max_length=500, unique=True, blank=True, null=True)
    date_created = models.DateTimeField(blank=True, null=True)
    last_updated = models.DateTimeField(blank=True, null=True)


class Results(models.Model):
    title = models.CharField(null=True, blank=True, max_length=100)
    number = models.CharField(null=True, blank=True, max_length=100)
    dueDate = models.DateField(null=True, blank=True)
    status = models.CharField(choices=STATUS, default='CURRENT', max_length=100)
    notes = models.TextField(null=True, blank=True)

    # 关联字段
    patient = models.ForeignKey(Patient, blank=True, null=True, on_delete=models.SET_NULL)

views.py

if request.method == 'POST':
        doc_form  = DoctorForm(request.POST)
        inv_form = ResultsForm(request.POST, instance=results)
        patients_form = PatientSelectForm(request.POST, initial_patient=results.patient, instance=results)

        if doc_form.is_valid():
            obj = doc_form.save(commit=False)
            obj.results = results
            obj.save()

            messages.success(request, "Results Doctor added succesfully")
            return redirect('create-build-results', slug=slug)
        elif inv_form.is_valid and 'paymentTerms' in request.POST:
            inv_form.save()

            messages.success(request, "Results updated succesfully")
            return redirect('create-build-results', slug=slug)
        elif patients_form.is_valid() and 'patient' in request.POST:

            patients_form.save()
            messages.success(request, "Client added to Results succesfully")
            return redirect('create-build-results', slug=slug)

forms.py

class PatientSelectForm(forms.ModelForm):

    def __init__(self,*args,**kwargs):
        self.initial_patient = kwargs.pop('initial_patient')
        self.PATIENT_LIST = Prescription.objects.all()
        self.PATIENT_CHOICES = [('-----', '--Select a Patient--')]
        for patient in self.PATIENT_LIST:
            d_t = (patient.uniqueId, patient.first_name)
            self.PATIENT_CHOICES.append(d_t)
        super(PatientSelectForm,self).__init__(*args,**kwargs)

        self.fields['patient'] = forms.ChoiceField(
                                        label='Choose a related patient',
                                        choices = self.PATIENT_CHOICES,
                                        widget=forms.Select(attrs={'class': 'form-control mb-3'}),)

    class Meta:
        model = Results
        fields = ['patient']

报错触发位置

elif patients_form.is_valid() and 'patient' in request.POST:

问题原因

  1. 用ChoiceField处理外键字段patient时,提交仅返回选中的uniqueId字符串,但外键字段需要的是Patient实例,导致类型不匹配。
  2. forms.py中错误从Prescription.objects.all()获取列表,应该从Patient模型取数据,否则拿到的不是Patient对象。

修复方案

方案一:改用ModelChoiceField(推荐)

Django自带的ModelChoiceField会自动处理实例与ID的转换,无需手动构造选项:

class PatientSelectForm(forms.ModelForm):
    def __init__(self,*args,**kwargs):
        self.initial_patient = kwargs.pop('initial_patient')
        super(PatientSelectForm,self).__init__(*args,**kwargs)
        # 替换为ModelChoiceField
        self.fields['patient'] = forms.ModelChoiceField(
            label='选择关联患者',
            queryset=Patient.objects.all(),
            empty_label='--Select a Patient--',
            widget=forms.Select(attrs={'class': 'form-control mb-3'}),
            required=False
        )
        # 设置初始选中值
        if self.initial_patient:
            self.fields['patient'].initial = self.initial_patient

    class Meta:
        model = Results
        fields = ['patient']

方案二:手动转换ID为实例(不推荐)

若坚持使用ChoiceField,需在表单中添加清洗方法将字符串转为实例:

class PatientSelectForm(forms.ModelForm):
    def __init__(self,*args,**kwargs):
        self.initial_patient = kwargs.pop('initial_patient')
        # 修正为从Patient模型取数据
        self.PATIENT_LIST = Patient.objects.all()
        self.PATIENT_CHOICES = [('-----', '--Select a Patient--')]
        for patient in self.PATIENT_LIST:
            d_t = (patient.uniqueId, patient.first_name)
            self.PATIENT_CHOICES.append(d_t)
        super(PatientSelectForm,self).__init__(*args,**kwargs)

        self.fields['patient'] = forms.ChoiceField(
                                        label='Choose a related patient',
                                        choices = self.PATIENT_CHOICES,
                                        widget=forms.Select(attrs={'class': 'form-control mb-3'}),
                                        required=False)

    def clean_patient(self):
        patient_id = self.cleaned_data.get('patient')
        if patient_id == '-----':
            return None
        try:
            return Patient.objects.get(uniqueId=patient_id)
        except Patient.DoesNotExist:
            raise forms.ValidationError("所选患者不存在")

    class Meta:
        model = Results
        fields = ['patient']

额外注意点

  • views.py中inv_form.is_valid少了括号,应改为inv_form.is_valid(),否则逻辑会出错。
  • 确保Patient模型的uniqueId字段唯一,避免get方法返回多个实例。

内容的提问来源于stack exchange,提问作者Loic Fieze

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.08.16 20:05:33