Django中从表单字段衍生的模型字段应在何处赋值?
问题解答
对于Django中无法和ModelForm字段直接映射的模型字段,推荐在ModelForm的clean()方法中完成赋值,这个执行时机刚好在表单自身校验完成后、模型层full_clean()方法调用之前,完全满足题中需要提前赋值再做模型校验的需求。
你可以按如下方式修改你的BlastForm实现:
from django import forms class BlastForm(forms.ModelForm): # 自定义的统一选择字段,可返回ProteinDB或NucleotideDB实例 blast_db = BlastDBField() class Meta: model = BlastQuery fields = ('foo',) def clean(self): cleaned_data = super().clean() # 拿到表单校验后的blast_db实例 blast_db = cleaned_data.get('blast_db') if blast_db: # 根据实例类型赋值给对应的模型字段 if isinstance(blast_db, ProteinDB): self.instance.protein_db = blast_db self.instance.nucleotide_db = None else: self.instance.nucleotide_db = blast_db self.instance.protein_db = None return cleaned_data
补充说明
- 赋值操作直接绑定到
self.instance上,这个对象就是后续要保存的模型实例,赋值后再调用模型的full_clean()或者form.save()都会直接使用你设置好的值,不会触发互斥/必填的校验报错。 - 不推荐把这段赋值逻辑放到视图层处理,会导致逻辑分散,多处使用同一个表单时需要重复写赋值代码,封装到Form层是复用性最高的实现。
内容的提问来源于stack exchange,提问作者Tim Diels
相关产品推荐
相关产品推荐

