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

Django车辆服务记录添加时Workshop字段类型错误求助

问题:无法为车辆创建ServiceRecord,触发TypeError错误

开发个人车辆在线服务手册项目,涉及Vehicle、Workshop、Filter、ServiceRecord模型,尝试为已添加车辆创建ServiceRecord时失败,报错信息及相关代码如下:

相关代码

forms.py

class ServiceRecordCreateForm(forms.ModelForm):
    def __init__(self, *args, **kwargs):
        super().__init__(*args, **kwargs)

        all_workshops = Workshop.objects.exclude(name="Other Workshop")
        workshop_choices = [(workshop.id, workshop.name) for workshop in all_workshops]
        workshop_choices.insert(0, (0, 'Other Workshop'))  
        self.fields['workshop'].widget = forms.Select(choices=workshop_choices)
        self.fields['workshop'].choices = workshop_choices

        
        all_filters = Filter.objects.all()
        filter_choices = [(filter.id, filter.name) for filter in all_filters]
        self.fields['filters_changed'].widget = forms.CheckboxSelectMultiple()
        self.fields['filters_changed'].choices = filter_choices

    def clean_workshop(self):
        workshop_id = self.cleaned_data.get('workshop')
        if workshop_id == 0:  # 处理"Other Workshop"情况
            workshop = Workshop.objects.filter(name="Other Workshop").first()
            if not workshop:
                raise forms.ValidationError("Other Workshop is not available.")
        else:
            workshop = Workshop.objects.get(id=workshop_id)
        return workshop

    class Meta:
        model = ServiceRecord
        fields = ['workshop', 'date', 'mileage_at_service', 'filters_changed']
        widgets = {
            'date': forms.DateInput(attrs={'type': 'date'}),
        }

views.py

class ServiceRecordCreateView(LoginRequiredMixin, CreateView):
    model = ServiceRecord
    form_class = ServiceRecordCreateForm
    template_name = 'create_service_record.html'

    def get_success_url(self):
        vehicle_id = self.kwargs['vehicle_id']
        return reverse_lazy('service_record_list', kwargs={'vehicle_id': vehicle_id})

    def form_valid(self, form):
        service_record = form.save(commit=False)
        service_record.vehicle_id = self.kwargs['vehicle_id']
        service_record.save()
        form.save_m2m()
        return redirect(self.get_success_url())

错误信息

TypeError at /create_service_record/2/
    Field 'id' expected a number but got <Workshop: Worksh1 (ALALALA)>.
    Request Method: POST
    Request URL:    http://127.0.0.1:8000/create_service_record/2/
    Django Version: 4.2.11
    Exception Type: TypeError
    Exception Value:    
    Field 'id' expected a number but got <Workshop: Worksh1 (ALALALA)>.
    Exception Location: /home/kamil/.local/lib/python3.10/site-packages/django/db/models/fields/__init__.py, line 2055, in get_prep_value
    Raised during:  servicebook.views.ServiceRecordCreateView
    Python Executable:  /usr/bin/python3
    Python Version: 3.10.12
    Python Path:    
['/home/kamil/workspace/car_care_log',
 '/usr/lib/python310.zip',
 '/usr/lib/python3.10',
 '/usr/lib/python3.10/lib-dynload',
 '/home/kamil/.local/lib/python3.10/site-packages',
 '/usr/local/lib/python3.10/dist-packages',
 '/usr/lib/python3/dist-packages']

解决方案

问题根源

clean_workshop方法返回的是Workshop对象,但Django ModelForm的外键字段期望清理后的值是主键ID(数字类型)。当对象被传入外键字段时,Django会尝试将其当作ID处理,从而触发类型错误。

修复步骤

修改clean_workshop方法,返回Workshop对象的ID而非对象本身:

def clean_workshop(self):
    workshop_id = self.cleaned_data.get('workshop')
    if workshop_id == 0:  # 处理"Other Workshop"情况
        workshop = Workshop.objects.filter(name="Other Workshop").first()
        if not workshop:
            raise forms.ValidationError("Other Workshop is not available.")
        workshop_id = workshop.id  # 获取实际主键ID
    else:
        # 可选:验证ID对应的Workshop是否存在,避免无效值
        try:
            Workshop.objects.get(id=workshop_id)
        except Workshop.DoesNotExist:
            raise forms.ValidationError("Invalid workshop selected.")
    return workshop_id

额外检查

确认ServiceRecord模型中的workshop字段是ForeignKey类型关联到Workshop模型,确保字段定义正确:

class ServiceRecord(models.Model):
    workshop = models.ForeignKey(Workshop, on_delete=models.CASCADE)
    # 其他字段...

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.06.24 12:22:13