Django中POHeaderForm的__init__方法失效,Widget属性未渲染求助
问题根源分析
你遇到的问题其实很清晰:你的PurchaseOrderCBV视图没有关联自定义的POHeaderForm,导致Django自动生成了一个默认的ModelForm,完全没用到你写的表单类,自然__init__方法里的Widget属性设置不会生效。
看你的视图代码,你只指定了model = POHeaderModel和fields = '__all__',这会让Django的CreateView动态创建一个临时的ModelForm子类,而非你定义的POHeaderForm。这也是为什么POBodyForm能正常渲染样式(因为你在POFormSet里显式指定了form=POBodyForm),但POHeaderForm的设置完全没起作用的原因。
解决方案
只需要在PurchaseOrderCBV里替换掉fields属性,显式指定form_class为你自定义的POHeaderForm即可:
class PurchaseOrderCBV(CreateView): model = POHeaderModel form_class = POHeaderForm # 替换原来的fields='__all__' success_url = reverse_lazy('purchase_order') def get_context_data(self, **kwargs): data = super().get_context_data(**kwargs) if self.request.POST: data['formbody'] = POFormSet(self.request.POST) else: data['formbody'] = POFormSet() return data def form_valid(self, form): context = self.get_context_data() formbody = context['formbody'] with transaction.atomic(): self.object = form.save() if formbody.is_valid(): formbody.instance = self.object formbody.save() return super().form_valid(form)
额外优化建议
- Python3里调用父类方法可以简化为
super().method(),不需要再传类和self参数,比如super().get_context_data(**kwargs)比super(PurchaseOrderCBV, self).get_context_data(**kwargs)更简洁。 - 你的
POHeaderForm和POBodyForm的__init__方法逻辑完全一致,可以抽成一个基类避免重复代码,后续修改样式时只需改动基类即可:
class BasePOForm(forms.ModelForm): def __init__(self, *args, **kwargs): super().__init__(*args, **kwargs) for field in self.fields: self.fields[field].widget.attrs = {'class': 'form-control form-control-sm'} class POHeaderForm(BasePOForm): class Meta: model = POHeaderModel fields = '__all__' class POBodyForm(BasePOForm): class Meta: model = POBodyModel fields = '__all__'
内容的提问来源于stack exchange,提问作者Lucid Polygon
相关产品推荐
相关产品推荐

