Django通过view传kwargs给Form设初始值外键字段失效问题
问题解答
1. 为什么打印输出两组值
你的表单一共被实例化了两次,对应两次打印输出:
- 第一次是用户发起GET请求访问页面时的实例化,此时你传入了ref、attribute_set等自定义参数,所以打印结果为
34、2; - 第二次是用户提交表单发起POST请求时的实例化,你的视图代码没有区分请求类型,POST请求实例化表单时仅传入了
request.POST,没有附带ref、attribute_set等自定义参数,kwargs中取不到对应值就触发了pop方法的默认值,所以打印结果为noref、9999。
你当前视图不管GET/POST都传入request.POST的写法本身也不符合Django的规范,也是触发该问题的诱因之一。
2. 为什么手动写死initial值可以正常运行
Django的外键类型表单字段渲染时,只要拿到匹配的主键值作为初始值,就可以正常选中对应选项。你手动写死34、2的情况下,两次表单实例化给initial赋的值都是正确的外键主键值,自然可以正常生效;而原来的写法中POST请求实例化表单时拿到的是和实际主键不匹配的默认值,自然无法正确赋值。
更优实现方式
不需要重写表单的__init__方法手动处理初始值,Django表单原生支持initial参数传递初始值,代码可以大幅简化:
views.py修改(区分请求类型,用initial传值)
def NavetteToFicheCreateView(request, pk): navette = Navette.objects.get(id=pk) # 构造初始值字典 initial = { 'ref': navette.id, 'attribute_set': navette.famille.pk, 'cost': navette.cost, 'qty': navette.qty, 'etat': navette.etat, 'etat_ebay': navette.etat.etat_ebay, 'ean': get_last_ean() } if request.method == 'POST': # POST请求如果需要保留初始值也要传入initial,避免验证失败回显时初始值丢失 form = NavetteToFicheForm(request.POST, initial=initial) if form.is_valid(): # 你的表单处理逻辑 [...] else: # GET请求仅传入初始值即可 form = NavetteToFicheForm(initial=initial) [...]
form.py修改
直接删除你自定义的__init__逻辑即可,Django会自动把initial字典中的值对应到表单字段的初始值。如果这些预填充的字段不需要用户修改,可以设置为隐藏/只读避免用户篡改:
class NavetteToFicheForm(forms.ModelForm): class Meta: model = 你的模型类 # 替换为你实际绑定的模型 fields = 你的字段列表 # 替换为你实际需要渲染的字段 widgets = { 'ref': forms.HiddenInput(), 'attribute_set': forms.HiddenInput(), # 其他不需要用户修改的字段都可以设置为HiddenInput }
内容的提问来源于stack exchange,提问作者Abpostman1
相关产品推荐
相关产品推荐

