Django物流报价模板故障:添加产品按钮失效及下拉显示异常
报价请求页面问题解决方案
针对你遇到的三个问题,逐一排查并解决如下:
1. 下拉菜单显示横线(空选项)
原因
QuoteProductForm中的product字段默认会添加一个空选项(横线),若数据库中无预先创建的Product实例,下拉框会显示空行。
解决方案
修改forms.py,为product字段设置empty_label=None,同时确保数据库中存在Product数据(可通过Django admin添加):
from django import forms from .models import Quote, QuoteProduct, Product class QuoteForm(forms.ModelForm): class Meta: model = Quote fields = ['name', 'email', 'address', 'ph_num', 'state', 'city', 'pincode'] class QuoteProductForm(forms.ModelForm): # 去掉下拉框的空选项,直接显示所有Product product = forms.ModelChoiceField(queryset=Product.objects.all(), empty_label=None) class Meta: model = QuoteProduct fields = ['product', 'quantity']
2. 出现删除复选框
原因
Django的inlineformset_factory默认开启删除功能,会自动添加DELETE复选框。
解决方案
修改views.py中的formset创建代码,添加can_delete=False参数:
from django.shortcuts import render, redirect from .forms import QuoteForm from .models import Quote, QuoteProduct from django.forms.models import inlineformset_factory def quote_form_view(request): # 添加can_delete=False关闭删除复选框 QuoteProductFormSet = inlineformset_factory(Quote, QuoteProduct, fields=('product', 'quantity'), extra=1, can_delete=False) if request.method == 'POST': quote_form = QuoteForm(request.POST) # POST请求需传入空Quote实例,确保formset绑定正确 quote_product_formset = QuoteProductFormSet(request.POST, instance=Quote()) if quote_form.is_valid() and quote_product_formset.is_valid(): quote_instance = quote_form.save(commit=False) order_id = quote_instance.generate_order_id() quote_instance.order_id = order_id quote_instance.save() quote_product_formset.instance = quote_instance quote_product_formset.save() return redirect('index') else: quote_form = QuoteForm() quote_product_formset = QuoteProductFormSet() return render(request, 'quote.html', {'quote_form': quote_form, 'quote_product_formset': quote_product_formset})
3. 添加产品按钮无法正常工作
原因
原JS代码的表单克隆逻辑存在缺陷:
- 错误使用
__prefix__替换字段名,但初始表单字段名带索引(如quote_product_set-0-product)而非__prefix__ - 未处理表单元素的
id和标签的for属性,导致新表单标签与输入框不关联 - 未清理克隆表单的错误样式和旧值
解决方案
替换quote.html中的JS代码为:
{% block jscript %} <script> const formContainer = document.getElementById('quote-product-forms'); const addProductBtn = document.getElementById('add-product-btn'); const totalForms = document.getElementById('id_quote_product_set-TOTAL_FORMS'); const formPrefix = 'quote_product_set'; addProductBtn.addEventListener('click', () => { const newFormIndex = parseInt(totalForms.value); const templateForm = document.querySelector('.quote-product-form'); const newForm = templateForm.cloneNode(true); // 替换所有字段的name、id和label的for属性 newForm.querySelectorAll('[name], [id], label[for]').forEach(element => { const indexRegex = new RegExp(`${formPrefix}-\\d+-`); if (element.name) { element.name = element.name.replace(indexRegex, `${formPrefix}-${newFormIndex}-`); } if (element.id) { element.id = element.id.replace(indexRegex, `${formPrefix}-${newFormIndex}-`); } if (element.tagName === 'LABEL' && element.getAttribute('for')) { element.setAttribute('for', element.getAttribute('for').replace(indexRegex, `${formPrefix}-${newFormIndex}-`)); } }); // 清空输入字段值并移除错误样式 newForm.querySelectorAll('input, select').forEach(field => { field.value = ''; field.classList.remove('is-invalid'); const errorElement = field.closest('.form-group').querySelector('.invalid-feedback'); if (errorElement) errorElement.remove(); }); formContainer.appendChild(newForm); totalForms.value = newFormIndex + 1; }); </script> {% endblock %}
内容的提问来源于stack exchange,提问作者crackjack111
相关产品推荐
相关产品推荐

