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

Django中ModelForm多对多字段数据无法插入问题求助

问题:Vendor模型的ManyToMany字段branch无法保存到数据库

我定义了Branch分支主表模型和Vendor供应商模型,其中Vendor的branch字段为ManyToManyField关联Branch。已创建对应的VendorForm模型表单,在Add_Vendor视图中处理表单提交。当前问题:Vendor基础数据可正常保存,但关联的branch字段数据无法插入数据库。


Branch模型代码

class Branch(models.Model): # Branch Master
    status_type = (
        ("a",'Active'),
        ("d",'Deactive'),
    )
    code = models.CharField(max_length=100, null=True, blank=True, default=None)
    name = models.CharField(max_length=100, unique=True)
    suffix = models.CharField(max_length=8, unique=True)
    Remark = models.CharField(max_length=200, null=True, blank=True)
    created_by = models.ForeignKey(User, on_delete=models.SET_NULL, null=True)
    create_at = models.DateTimeField(auto_now_add=True)
    update_at = models.DateTimeField(auto_now=True)
    status = models.CharField(max_length=1, choices = status_type, default = 'a')
    def __str__(self):
        return self.name

Vendor模型代码

class Vendor(models.Model):
    status_type = (
        ("a",'Active'),
        ("d",'Deactive'),
    )
    code = models.CharField(max_length=100, null=True, blank=True, default=None)
    branch = models.ManyToManyField(Branch)
    company = models.CharField(max_length=200)
    name = models.CharField(max_length=200)
    phone = models.CharField(max_length=11, unique = True)
    email  =  models.EmailField(max_length=254, unique = True)
    gst = models.CharField(max_length=15, unique = True)
    pan_no = models.CharField(max_length=10, unique = True)
    add_1 = models.CharField(max_length=50, null=True, blank = True)
    add_2 = models.CharField(max_length=50, null=True, blank = True)
    add_3 = models.CharField(max_length=50, null=True, blank = True)
    city = models.CharField(max_length=50, default=None)
    state = models.CharField(max_length=50, default=None)
    Remark = models.CharField(max_length=200, null=True, blank=True)
    created_by = models.ForeignKey(User, on_delete=models.CASCADE)
    create_at = models.DateTimeField(auto_now_add=True)
    update_at = models.DateTimeField(auto_now=True)
    status = models.CharField(max_length=1, choices = status_type, default = 'a')

forms.py代码

class VendorForm(ModelForm):
    class Meta:
        model  = Vendor
        fields = '__all__'
        labels = {
            'add_1':'Address',
            'add_2':'Address',
            'add_3':'Address',
        }
        exclude = ['created_by']
        widgets = {
            'branch':forms.CheckboxSelectMultiple(attrs={'class':'',}),
            'company':forms.TextInput(attrs={'class':'form-control', 'placeholder':'Company Name'}),
            'name':forms.TextInput(attrs={'class':'form-control', 'placeholder':'Name'}),
            'phone':forms.TextInput(attrs={'class':'form-control', 'placeholder':'Phone'}),
            'email':forms.EmailInput(attrs={'class':'form-control', 'placeholder':'Email'}),
            'gst':forms.TextInput(attrs={'class':'form-control', 'placeholder':'GST No.'}),
            'pan_no':forms.TextInput(attrs={'class':'form-control', 'placeholder':'Pan No.'}),
            'add_1':forms.TextInput(attrs={'class':'form-control', 'placeholder':'Address'}),
            'add_2':forms.TextInput(attrs={'class':'form-control', 'placeholder':'Address'}),
            'add_3':forms.TextInput(attrs={'class':'form-control', 'placeholder':'Address'}),
            'city':forms.TextInput(attrs={'class':'form-control', 'placeholder':'City'}),
            'state':forms.TextInput(attrs={'class':'form-control', 'placeholder':'State'}),
            'Remark':forms.Textarea(attrs={'class':'form-control','rows':'2', 'placeholder':'Remark'}),
            'status':forms.Select(attrs={'class':'form-control'}),
        }

views.py代码

def Add_Vendor(request): # for vendor add
    if request.method == "POST":
        try:
            form = VendorForm(request.POST)
            if form.is_valid:
                forms = form.save(commit=False)
            forms.created_by = request.user
            forms.save()
                messages.success(request,'Vendor has been added.')
                return redirect('vendor_page')
        except:
            messages.error(request, str(form.errors))
            print(form.errors)
    else:
        form = VendorForm()
    context = {
        'form':form,
        'branch_data':request.session['branch_name'],
        'btn_type':'fa fa-regular fa-plus',
        'form_title':'Vendor Form',
        'tree_main_title':'Vendor',
        'v_url':'vendor_page',
        'tree_title':'Add Form',
    }
    return render(request, 'base/vendor_master/form_vendor.html', context)

问题原因及修复方法

1. 表单验证逻辑错误

代码中if form.is_valid:只是引用了方法对象,并未执行验证操作,必须改为if form.is_valid():才能触发表单验证,否则后续的关联数据处理逻辑不会执行。

2. 未手动保存ManyToMany关联数据

使用form.save(commit=False)时,Django不会自动保存ManyToMany字段的数据,因为这类数据需要关联已持久化的模型实例。需在保存Vendor基础数据后,调用form.save_m2m()来完成关联数据的插入。

修复后的views.py代码

def Add_Vendor(request): # for vendor add
    if request.method == "POST":
        try:
            form = VendorForm(request.POST)
            # 修复:执行表单验证,添加括号
            if form.is_valid():
                # 暂存未提交的Vendor实例
                vendor = form.save(commit=False)
                vendor.created_by = request.user
                # 保存Vendor基础数据到数据库
                vendor.save()
                # 保存ManyToMany字段的关联数据
                form.save_m2m()
                messages.success(request,'Vendor has been added.')
                return redirect('vendor_page')
            else:
                # 表单验证失败时返回错误
                messages.error(request, str(form.errors))
                print(form.errors)
        except Exception as e:
            messages.error(request, str(e))
            print(str(e))
    else:
        form = VendorForm()
    context = {
        'form':form,
        'branch_data':request.session['branch_name'],
        'btn_type':'fa fa-regular fa-plus',
        'form_title':'Vendor Form',
        'tree_main_title':'Vendor',
        'v_url':'vendor_page',
        'tree_title':'Add Form',
    }
    return render(request, 'base/vendor_master/form_vendor.html', context)

额外检查点

  • 确认模板中branch字段的多选框正确渲染,且在<form>标签内,提交时能传递选中值
  • 排查是否有中间件或权限限制过滤了branch字段的POST数据

内容的提问来源于stack exchange,提问作者shyam rathod

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.07.15 05:17:02