Django 3.0表单clean方法无法获取production_process值的问题求助
问题分析与修复方案
错误根源
production_process字段QuerySet错误:该字段是ForeignKey,对应表单的ModelChoiceField要求QuerySet返回模型实例,但你用values_list("name", flat=True)返回了字符串列表,导致表单提交时,选择的工序ID无法与QuerySet中的字符串匹配,触发「无效选择」验证错误。- clean方法逻辑混乱:原代码中try-except块滥用,且在未验证
production_process是否存在的情况下直接调用production_process.id,会引发属性错误;重复记录检查的逻辑也存在逻辑错误。
修复步骤
1. 修正production_process字段的QuerySet
在表单__init__方法中,将QuerySet改为返回当前客户下未删除的ProductionProcess实例:
class ProductionCapacityForm(forms.ModelForm): date = forms.DateField(required=True, widget=forms.DateInput(attrs={ 'class':'datepicker' })) def __init__(self, *args, **kwargs): self.client = kwargs.pop('client') self.request = kwargs.pop('request') try: self.work_time = kwargs.pop('work_time') except KeyError: pass super(ProductionCapacityForm, self).__init__(*args, **kwargs) # 修正:返回ProductionProcess实例,过滤当前客户+未删除的工序 self.fields['production_process'].queryset = ProductionProcess.objects.filter( client=self.client, is_deleted=False ).distinct() self.fields['date'].widget.attrs.update({ 'placeholder': 'Select Date', 'class': 'input-class_name' })
2. 重构clean方法的验证逻辑
修复重复记录检查逻辑,避免属性错误:
def clean(self): cleaned_data = super().clean() production_process = cleaned_data.get('production_process') number_of_people = cleaned_data.get('number_of_people') datee = cleaned_data.get('date') pk = self.instance.pk # 仅当所有必填字段都存在时检查重复 if production_process and datee: # 构建查询条件:匹配当前客户、日期、工序 duplicate_query = ProductionCapacity.objects.filter( client=self.client, date=datee, production_process=production_process ) # 编辑模式下排除当前实例 if pk: duplicate_query = duplicate_query.exclude(pk=pk) # 存在重复则抛出错误 if duplicate_query.exists(): raise forms.ValidationError('该生产工序在当日已存在记录') # 保留字段值(原逻辑无需修改,直接返回cleaned_data即可) return cleaned_data
3. 补充模型依赖(若缺失)
确保ProductionProcess模型包含client外键(否则clean方法中的client=self.client会报错):
# models.py class ProductionProcess(models.Model): client = models.ForeignKey(Client, on_delete=models.CASCADE) name = models.CharField(max_length=255) is_deleted = models.BooleanField(default=False) # 其他自定义字段...
修复说明
- 修正QuerySet后,
ModelChoiceField会正确渲染工序名称(默认显示模型__str__方法返回值),提交时传递的工序ID能与QuerySet中的实例匹配,解决「无效选择」错误。 - 重构后的clean方法先调用父类
clean()获取合法的cleaned_data,再进行重复检查,逻辑清晰且避免了属性错误。
内容的提问来源于stack exchange,提问作者Hari
相关产品推荐
相关产品推荐

