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

huangapple go评论56阅读模式
英文:

Django model form many to many field data how to insert?

问题

以下是您要翻译的内容:

**分支模型用于按分支分离数据**

class Branch(models.Model): # 分支主表
    status_type = (
        ("a", '激活'),
        ("d", '停用'),
    )
    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", '激活'),
        ("d", '停用'),
    )
    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': '地址',
            'add_2': '地址',
            'add_3': '地址',
        }
        exclude = ['created_by']
        widgets = {
            'branch': forms.CheckboxSelectMultiple(attrs={'class': ''}),
            'company': forms.TextInput(attrs={'class': 'form-control', 'placeholder': '公司名称'}),
            'name': forms.TextInput(attrs={'class': 'form-control', 'placeholder': '名称'}),
            'phone': forms.TextInput(attrs={'class': 'form-control', 'placeholder': '电话'}),
            'email': forms.EmailInput(attrs={'class': 'form-control', 'placeholder': '电子邮件'}),
            'gst': forms.TextInput(attrs={'class': 'form-control', 'placeholder': 'GST号'}),
            'pan_no': forms.TextInput(attrs={'class': 'form-control', 'placeholder': 'PAN号'}),
            'add_1': forms.TextInput(attrs={'class': 'form-control', 'placeholder': '地址'}),
            'add_2': forms.TextInput(attrs={'class': 'form-control', 'placeholder': '地址'}),
            'add_3': forms.TextInput(attrs={'class': 'form-control', 'placeholder': '地址'}),
            'city': forms.TextInput(attrs={'class': 'form-control', 'placeholder': '城市'}),
            'state': forms.TextInput(attrs={'class': 'form-control', 'placeholder': '州'}),
            'Remark': forms.Textarea(attrs={'class': 'form-control', 'rows': '2', 'placeholder': '备注'}),
            'status': forms.Select(attrs={'class': 'form-control'}),
        }

**View.py中ManyToMany字段没有插入到数据库中我不知道问题在哪里供应商数据已保存但分支字段没有保存**

def Add_Vendor(request): # 用于添加供应商
    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, '供应商已添加。')
                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': '供应商表单',
        'tree_main_title': '供应商',
        'v_url': 'vendor_page',
        'tree_title': '添加表单',
    }
    return render(request, 'base/vendor_master/form_vendor.html', context)

请注意,我已经将HTML标签中的特殊字符转义为普通文本,以便更容易阅读。如果您需要原始HTML代码,请将特殊字符重新转义。

英文:

Branch Model which to separate to data branch wise

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 Model which is I am use to separate branch wise vendors

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

**this is forms.py file **

    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 Many to Many field is not insert i don't know what is problem vendor data is save but branch is field is not save **

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)

**Vendor data save into data base but branch field is not insert into database **

答案1

得分: 1

就像之前一样,不要使用commit=False:它默认情况下会阻止保存多对多字段。

您的if form.is_valid总是成功,因为它是一个方法,而方法的真值为True

def Add_Vendor(request):  # 用于添加供应商
    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, '供应商已添加。')
            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': '供应商表格',
        'tree_main_title': '供应商',
        'v_url': 'vendor_page',
        'tree_title': '添加表格',
    }
    return render(request, 'base/vendor_master/form_vendor.html', context)

话虽如此,会话变量通常不是一个好主意。实际上,它会创建某种全局状态反模式,并且不难想象,在某人通过某个其他页面视图之前,会话变量可能会发生更改/失效。因此,会给人一种错误的印象,即它将与不同的分支一起工作。通常更好的做法是显式地添加一个包含主键或分支的其他令牌的路径参数。

Branch模型不应该更新,它只是添加一个链接。这意味着myvendor.branch.all()现在应该返回那个Branch,因此它们将两者关联在一起,关联两个项目不会修改(各自的)项目,因此时间戳将不会更新。

注意: 函数通常使用蛇形命名法编写,而不是帕斯卡命名法,因此建议将函数重命名为add_vendor,而不是Add_Vendor

注意: 通常更好的做法是使用settings.AUTH_USER_MODEL来引用用户模型,而不是直接使用**User**模型。有关更多信息,您可以查看文档中的引用User模型部分

注意: 通常更好的做法是使用get_object_or_404(…),而不是直接使用.get(…)。如果对象不存在,例如因为用户自己更改了URL,那么get_object_or_404(…)将返回HTTP 404 Not Found响应,而使用get(…)将导致HTTP 500 Server Error

注意: 虽然大多数表单不处理媒体文件,但最好还是将request.FILES传递给表单,以便如果以后添加额外的媒体字段,所有使用该表单的视图都可以正确处理文件。

英文:

Just like the previous time, don't use commit=False: it prevents saving the many-to-many fields by default.

Your if form.is_valid will always succeed, since it is a method, and a method has truthiness True:

<pre><code>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()
<b>vendor_add.branch.add(branch)</b>
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)</code></pre>

That being said, session variables are often not a good idea. Indeed, it creates some sort of global state antipattern [softwareengineering.se], and it is not unthinkable that just before a person makes a request to the page, through some other page view, the session variables change/invalidate. Therefore giving the wrong impression that it will work with a different branch. Usually it is better to do things explicitly and thus add a parameter to the path that contains the primary key, or some other token of the branch to add.

The Branch model is however not suposed to update, it simply adds a link. That means that myvendor.branch.all() should now return that Branch, it thus links the two together, linking two items does not modify the (individual) items, hence the timestamp will not update.


> Note: Functions are normally written in snake_case, not PascalCase, therefore it is
> advisable to rename your function to add_vendor, not <s>Add_Vendor</s>.


> Note: It is normally better to make use of the settings.AUTH_USER_MODEL&nbsp;<sup>[Django-doc]</sup> to refer to the user model, than to use the User model&nbsp;<sup>[Django-doc]</sup> directly. For more information you can see the referencing the User model section of the documentation.


> Note: It is often better to use <code>get_object_or_404(&hellip;)</code>&nbsp;<sup>[Django-doc]</sup>,
> then to use <code>.get(&hellip;)</code>&nbsp;<sup>[Django-doc]</sup> directly. In case the object does not exists,
> for example because the user altered the URL themselves, the <code>get_object_or_404(&hellip;)</code> will result in returning a HTTP 404 Not Found response, whereas using
> <code>.get(&hellip;)</code> will result in a HTTP 500 Server Error.


> Note: While most forms do not process media files, it is probably better to pass request.FILES&nbsp;<sup>[Django-doc]</sup> to the form anyway, such that if you later add an extra media field, all views that use the form will indeed handle the files properly.g

答案2

得分: 0

在你的views.py文件中,表单验证存在问题。你应该使用:

if form.is_valid():

并且你应该确保"branch_id"存在。

要将分支添加到供应商,你应该先保存供应商对象但不提交到数据库,然后将分支添加到供应商,然后再次保存供应商对象,所以“Add_Vendor”函数应该像这样:

def Add_Vendor(request): # 用于添加供应商
    b_id = request.session['branch_id']
    # 检查b_id是否存在
    if b_id is None:
        messages.error(request, '未选择分支。请先选择一个分支。')
        return redirect('select_branch_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() # 再次保存供应商以保持对分支的更改。
            messages.success(request, '供应商已添加。')
            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':'供应商表单',
        'tree_main_title':'供应商',
        'v_url':'vendor_page',
        'tree_title':'添加表单',
    }
    return render(request, 'base/vendor_master/form_vendor.html', context)

希望对你有所帮助。

英文:

there is a problem with form validation in your views.py
you should use:

if form.is_valid():

and you should make sure that the "branch_id" exists

to add branch to vendor, you should first save the vendor object without committing to database then add the branch to vendor and then save the vendor object again so the "Add_Vendor" function should be like this:

def Add_Vendor(request): # for vendor add
b_id = request.session[&#39;branch_id&#39;]
# check if b_id exists
if b_id is None:
messages.error(request, &#39;Branch not selected. Please select a branch first.&#39;)
return redirect(&#39;select_branch_page&#39;) # redirect to the branch selecting page
branch_id = Branch.objects.get(id = b_id)
print(branch_id)
if request.method == &quot;POST&quot;:
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, &#39;Vendor has been added.&#39;)
return redirect(&#39;vendor_page&#39;)
else:
messages.error(request, str(form.errors))
print(form.errors)
else:
form = VendorForm()
context = {
&#39;form&#39;:form,
&#39;branch_data&#39;:request.session[&#39;branch_name&#39;],
&#39;btn_type&#39;:&#39;fa fa-regular fa-plus&#39;,
&#39;form_title&#39;:&#39;Vendor Form&#39;,
&#39;tree_main_title&#39;:&#39;Vendor&#39;,
&#39;v_url&#39;:&#39;vendor_page&#39;,
&#39;tree_title&#39;:&#39;Add Form&#39;,
}
return render(request, &#39;base/vendor_master/form_vendor.html&#39;, context)

I hope this helps you.

huangapple
  • 本文由 发表于 2023年7月24日 19:11:59
  • 转载请务必保留本文链接:https://go.coder-hub.com/76753892.html
匿名

发表评论

匿名网友

:?: :razz: :sad: :evil: :!: :smile: :oops: :grin: :eek: :shock: :???: :cool: :lol: :mad: :twisted: :roll: :wink: :idea: :arrow: :neutral: :cry: :mrgreen:

确定