You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

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

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.06.28 08:12:02