Django模型表单多对多字段数据如何插入?

kulphzqa  于 2023-08-08  发布在  Go
关注(0)|答案(2)|浏览(137)

要按分支方式分离到数据的分支模型

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

字符串

供应商模型,我用来区分分支供应商

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'}),
            }

View.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)

供应商数据保存到数据库,但分支字段未插入数据库

a1o7rhls

a1o7rhls1#

就像上一次一样,* 不要 * 使用commit=False:默认情况下,它防止保存多对多字段。
你的if form.is_valid将 * 总是 * 成功,因为它是一个方法,而一个方法具有真实性True

def Add_Vendor(request):  # for vendor add
    branch = get_object_or_404(Branch, pk=request.session['branch_id'])
    if request.method == 'POST':
        form = VendorForm(request.POST, request.FILES)
        if form.is_valid():
            form.instance.created_by = request.user
            vendor_add = form.save()
            vendor_add.branch.add(branch)
            messages.success(request, 'Vendor has been added.')
            return redirect('vendor_page')
        else:
            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)

字符串
话虽如此,会话变量通常不是一个好主意。事实上,它创建了某种global state antipattern [softwareengineering.se],并且在用户通过其他页面视图向页面发出请求之前,会话变量发生更改/无效也是不可想象的。因此,给人一种错误的印象,认为它将与不同的分支一起工作。通常,最好是显式地执行这些操作,从而在包含主键的路径中添加一个参数,或者要添加的分支的其他标记。
然而,Branch模型并不需要更新,它只是添加了一个链接。这意味着myvendor.branch.all()现在应该返回Branch,因此它将两者链接在一起,链接两个项目不会修改(单个)项目,因此时间戳不会更新。

注意:函数一般用 snake_case 编写,而不是 PascalCase,因此建议将函数重命名为add_vendor,而不是Add_Vendor
注意:通常使用**settings.AUTH_USER_MODEL[Django-doc]来引用用户模型,而不是直接使用User模型[Django-doc]。有关更多信息,请参阅文档的 * 引用User型号 * 部分。
注意:通常使用
get_object_or_404(…)[Django-doc]比直接使用.get(…)[Django-doc]更好。如果对象不存在,例如因为用户自己修改了URL,get_object_or_404(…)将导致返回 HTTP 404 Not Found 响应,而使用.get(…)将导致 HTTP 500 Server Error
注意:虽然大多数表单不处理媒体文件,但最好还是将
request.FILES**[Django-doc]传递给表单,这样,如果你以后添加了一个额外的媒体字段,所有使用表单的视图都会正确处理这些文件。

nzkunb0c

nzkunb0c2#

您的views.py中的表单验证存在问题,您应该用途:

if form.is_valid():

字符串
并且您应该确保“分支_id”存在
要添加分支到vendor,您应该首先保存vendor对象,而不提交到数据库,然后将branch添加到vendor,然后再次保存vendor对象,因此“Add_Vendor”函数应该是这样的:

def Add_Vendor(request): # for vendor add
    b_id = request.session['branch_id']
    # check if b_id exists
    if b_id is None:
        messages.error(request, 'Branch not selected. Please select a branch first.')
        return redirect('select_branch_page') # redirect to the branch selecting page

    branch_id = Branch.objects.get(id = b_id)
    print(branch_id)
    if request.method == "POST":
        form = VendorForm(request.POST)
        if form.is_valid():
            vendor_add = form.save(commit=False)
            vendor_add.created_by = request.user
            vendor_add.save()
            vendor_add.branch.add(branch_id)
            vendor_add.save() # Save the vendor again to persist the changes with the branch.
            messages.success(request, 'Vendor has been added.')
            return redirect('vendor_page')
        else:
            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)


我希望这对你有帮助。

相关问题