如何在Django模板中向modelform_factory传递行ID参数
解决方法
方法一:在表单类中添加隐藏字段(推荐)
这种方法更规范,能利用Django表单的验证机制,避免手动处理字段命名的问题。
- 定义表单类
在forms.py里给你的发放表单添加一个隐藏字段,用来存储对应产品的ID:
from django import forms from .models import Issuance class IssuanceForm(forms.ModelForm): # 隐藏字段,用于传递产品ID product_id = forms.IntegerField(widget=forms.HiddenInput()) class Meta: model = Issuance fields = ['checked', 'factory'] # 替换成你实际需要的字段
- 视图中初始化Formset并绑定产品ID
在视图里根据products_info的数量生成Formset,同时给每个表单的product_id赋值对应产品的ID:
from django.forms import formset_factory from .forms import IssuanceForm from .models import Product # 替换成你的产品模型 def issuance_view(request): products_info = Product.objects.all() # 你的产品查询逻辑 # 生成Formset,数量和产品列表一致 IssuanceFormSet = formset_factory(IssuanceForm, extra=len(products_info)) if request.method == 'POST': formset = IssuanceFormSet(request.POST) if formset.is_valid(): for form in formset: # 可选:只处理勾选过的行 if form.cleaned_data.get('checked'): issuance = form.save(commit=False) # 从表单获取产品ID并关联到发放记录 issuance.product_id = form.cleaned_data['product_id'] issuance.save() # 处理成功后的跳转或提示 return redirect('shop:some_success_page') else: # 初始化Formset,给每个表单传入产品ID的初始值 initial_data = [{'product_id': product.id} for product in products_info] formset = IssuanceFormSet(initial=initial_data) # 将产品列表和Formset的表单一一对应传入模板 context = { 'products_form_pairs': zip(products_info, formset.forms), 'issuance_formset': formset } return render(request, 'your_template.html', context)
- 模板中渲染表单和产品信息
模板里循环配对后的产品和表单,同时必须渲染Formset的管理表单(放在<form>标签内):
<form method="post"> {% csrf_token %} <!-- 必须渲染Formset的管理表单,否则无法正确提交 --> {{ issuance_formset.management_form }} <table> {% for product, form in products_form_pairs %} <tr> <td>{{ form.checked }}</td> <td> <a href="#" class="open-modal" data-url="{% url 'shop:item_modal' product.id %}"> {{ product.item.name }} </a> </td> <td>{{ form.factory }}</td> <!-- 隐藏字段会自动渲染,无需手动添加 --> {{ form.product_id }} </tr> {% endfor %} </table> <button type="submit">提交</button> </form>
方法二:模板中手动添加隐藏字段
如果不想修改表单类,可以直接在模板里为每一行添加隐藏字段,注意要符合Formset的字段命名规则:
- 视图调整
视图里无需修改表单类,只需将产品列表和Formset的表单配对传入模板:
from django.forms import formset_factory from .forms import YourExistingIssuanceForm from .models import Product def issuance_view(request): products_info = Product.objects.all() IssuanceFormSet = formset_factory(YourExistingIssuanceForm, extra=len(products_info)) formset = IssuanceFormSet() if request.method != 'POST' else IssuanceFormSet(request.POST) if request.method == 'POST' and formset.is_valid(): for idx, form in enumerate(formset): if form.cleaned_data.get('checked'): issuance = form.save(commit=False) # 从POST数据中获取对应行的产品ID product_id = request.POST.get(f'form-{idx}-product_id') issuance.product_id = product_id issuance.save() return redirect('shop:some_success_page') context = { 'products_form_pairs': zip(products_info, formset.forms), 'issuance_formset': formset } return render(request, 'your_template.html', context)
- 模板渲染
在循环里手动添加隐藏字段,命名格式为form-索引-product_id:
<form method="post"> {% csrf_token %} {{ issuance_formset.management_form }} <table> {% for idx, (product, form) in enumerate(products_form_pairs) %} <tr> <td>{{ form.checked }}</td> <td> <a href="#" class="open-modal" data-url="{% url 'shop:item_modal' product.id %}"> {{ product.item.name }} </a> </td> <td>{{ form.factory }}</td> <!-- 手动添加隐藏字段,对应Formset的命名规则 --> <input type="hidden" name="form-{{ idx }}-product_id" value="{{ product.id }}"> </tr> {% endfor %} </table> <button type="submit">提交</button> </form>
内容的提问来源于stack exchange,提问作者DEV
相关产品推荐
相关产品推荐

