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:
问题原因
- 用
ChoiceField处理外键字段patient时,提交仅返回选中的uniqueId字符串,但外键字段需要的是Patient实例,导致类型不匹配。 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
相关产品推荐
相关产品推荐

