将 Javascript 计算传递给 Django 后端
Pass Javascript Calculations to Django Backend
我有一个 HTML 表单,用户在输入表单中输入项目的名称和对应的值,当表单提交到 Django 后端时反映出来。
在我的 HTML 表单中,我包含了一些 Javascript 以便立即反映这些值的总和,而无需刷新,甚至在提交表单之前。
我的目标:
发送idTotal
下HTML中Javascript计算的总金额
<th scope="col">Total Equipment and Assets</th>
<th scope="col" id="Total"></th>
到
中的class
total_assets= models.IntegerField(null=True, blank=True, verbose_name='Total Assets')
在Models.py提交后。
请注意,问题的原因是合计值不是手动添加的,而是使用 Javascript 直接计算的。
这里有一个示例,可以使事情更清楚。
这是 HTML 模板:
<tr>
<td>
<input
placeholder="Type in the Equipment and assets"
type="text"
class="form-control"
name="item_1"
id="item_1"
{% if form.is_bound %}value="{{ form.item_1.value }}"{% endif %}/>
{% for err in form.item_1.errors %}
<small class="text-danger mb-2 ml-2">{{ err }}</small>
{% endfor %}
</td>
<td>
<h6 style="float:left; margin-right:5px; margin-top:7px">$</h6>
<input
type="number"
class="form-control w-25 subtotal-group subtotal-group-1"
name="item_1_amount"
id="item_1_amount"
{% if form.is_bound %}value="{{ form.item_1_amount.value }}"{% endif %}/>
{% for err in form.item_1_amount.errors %}
<small class="text-danger mb-2 ml-2">{{ err }}</small>
{% endfor %}
</td>
</tr>
<tr>
<td>
<input
placeholder="Type in the Equipment and assets"
type="text"
class="form-control"
name="item_2"
id="item_2"
{% if form.is_bound %}value="{{ form.item_2.value }}"{% endif %}/>
{% for err in form.item_2.errors %}
<small class="text-danger mb-2 ml-2">{{ err }}</small>
{% endfor %}
</td>
<td>
<h6 style="float:left; margin-right:5px; margin-top:7px">$</h6>
<input
autocomplete="off"
type="number"
class="form-control w-25 subtotal-group subtotal-group-1"
name="item_2_amount"
id="item_2_amount"
{% if form.is_bound %}value="{{ form.item_2_amount.value }}"{% endif %}/>
{% for err in form.item_2_amount.errors %}
<small class="text-danger mb-2 ml-2">{{ err }}</small>
{% endfor %}
</td>
</tr>
这是 Javacript
<script>
const q=(e,n=document)=>n.querySelector(e);
const qa=(e,n=document)=>n.querySelectorAll(e);
const results={};
console. log(results)
qa('[type="number"].form-control').forEach(input=>input.addEventListener('input',function(e){
results[ this.name ]=Number( this.value );
const resultGroupSet1 = [...qa('.subtotal-group-1')]
.map(s => Number(s.value))
.reduce((a,v) => a+v);
q('th#Total').textContent = resultGroupSet1;
}));
</script>
这里是 HTML 模板
中反映总数的地方
<thead class="table-light">
<tr>
<th scope="col">Total Equipment and Assets</th>
<th scope="col" id="Total"></th>
</tr>
</thead>
这是models.py
item_1 = models.CharField(max_length=100,null=True, blank=True, verbose_name='Item 1')
item_1_amount = models.IntegerField(null=True, blank=True, verbose_name='Item 1 Amount')
item_2 = models.CharField(max_length=100,null=True, blank=True, verbose_name='Item 2')
item_2_amount = models.IntegerField(null=True, blank=True, verbose_name='Item 2 Amount')
total_assets = models.IntegerField(null=True, blank=True, verbose_name='Total Assets')
观点如下:
def add_bp(request):
if request.method == 'POST':
# create a form instance and populate it with data from the request:
form = infoForm(request.POST)
# check whether it's valid:
if form.is_valid():
form.save()
b_name = form.cleaned_data.get('bName')
messages.success(request, f'PDF created for {b_name}!')
return redirect('application:core')
# if a GET (or any other method) we'll create a blank form
else:
form = infoForm()
return render(request, 'application/template.html', {'form': form, })
我假设您的问题是如何获取此元素中的值:
<th scope="col" id="Total"></th>
您只需在 html 代码中添加输入元素并将名称添加到其中:
<th scope="col"><input id="Total" name="total_assets" value=""></th>
然后在你的 views.py:
def add_bp(request):
if request.method == 'POST':
form = infoForm(request.POST)
if form.is_valid():
form.save()
您也可以手动获取总数:
def add_bp(request):
if request.method == 'POST':
total_assets = request.POST.get("total_assets")
可能您要找的是 <input type="hidden" ...>
,最终用户看不到它,它包含在表单提交中
将html更新为:
<thead class="table-light">
<tr>
<th scope="col">Total Equipment and Assets</th>
<th scope="col">
<!-- Value which is visible (calculated using JS) -->
<span id="Total"></span>
<!-- Add a hidden input to store value (value calculated and assigned using JS) -->
<input type="hidden" name="total_assets" value="0" id="total_assets">
</th>
</tr>
</thead>
更新脚本以将 resultGroupSet1
分配为:
- 带有
id=Total
的 span 标签的文本内容
- 隐藏输入的值
name=total_assets
// Assign result to span tag which is visible
q('span#Total').textContent = resultGroupSet1;
// Assign result as value to hidden input field with name total_assets
q('input#total_assets').value = resultGroupSet1;
视图没有其他变化。
由于使用了带有 name="total_assets"
的输入字段,该值将被传递到请求正文,并且可以在 request.POST
处访问。在这里,由于 total_assets
字段是隐藏的,所以它对用户不可见,并且在提交表单时该值在 POST 数据中仍然可用。所以,当调用 form.save()
时,计算值(使用 JS)将被保存。
为什么不在 Django 后端进行这个计算?
我的建议是正常传递所有参数,只为模型保存添加一个监听器(每次你将一个元素保存到table这一小段代码将运行正确在保存之前):
from django.db.models.signals import pre_save
from django.dispatch import receiver
@receiver(pre_save, model_class)
def form_pre_save(instance, *args, **kwargs):
instance.total_assets = instance.item_1_amount + instance.item_2_amount
这样当您想将这种元素保存在不同的地方(例如在后端)时,您不必重新编写执行此操作的代码,而只需保存实例。
您可以阅读有关信号 pre_save 函数的更多信息 here
我有一个 HTML 表单,用户在输入表单中输入项目的名称和对应的值,当表单提交到 Django 后端时反映出来。
在我的 HTML 表单中,我包含了一些 Javascript 以便立即反映这些值的总和,而无需刷新,甚至在提交表单之前。
我的目标:
发送idTotal
<th scope="col">Total Equipment and Assets</th>
<th scope="col" id="Total"></th>
到
中的classtotal_assets= models.IntegerField(null=True, blank=True, verbose_name='Total Assets')
在Models.py提交后。
请注意,问题的原因是合计值不是手动添加的,而是使用 Javascript 直接计算的。
这里有一个示例,可以使事情更清楚。
这是 HTML 模板:
<tr>
<td>
<input
placeholder="Type in the Equipment and assets"
type="text"
class="form-control"
name="item_1"
id="item_1"
{% if form.is_bound %}value="{{ form.item_1.value }}"{% endif %}/>
{% for err in form.item_1.errors %}
<small class="text-danger mb-2 ml-2">{{ err }}</small>
{% endfor %}
</td>
<td>
<h6 style="float:left; margin-right:5px; margin-top:7px">$</h6>
<input
type="number"
class="form-control w-25 subtotal-group subtotal-group-1"
name="item_1_amount"
id="item_1_amount"
{% if form.is_bound %}value="{{ form.item_1_amount.value }}"{% endif %}/>
{% for err in form.item_1_amount.errors %}
<small class="text-danger mb-2 ml-2">{{ err }}</small>
{% endfor %}
</td>
</tr>
<tr>
<td>
<input
placeholder="Type in the Equipment and assets"
type="text"
class="form-control"
name="item_2"
id="item_2"
{% if form.is_bound %}value="{{ form.item_2.value }}"{% endif %}/>
{% for err in form.item_2.errors %}
<small class="text-danger mb-2 ml-2">{{ err }}</small>
{% endfor %}
</td>
<td>
<h6 style="float:left; margin-right:5px; margin-top:7px">$</h6>
<input
autocomplete="off"
type="number"
class="form-control w-25 subtotal-group subtotal-group-1"
name="item_2_amount"
id="item_2_amount"
{% if form.is_bound %}value="{{ form.item_2_amount.value }}"{% endif %}/>
{% for err in form.item_2_amount.errors %}
<small class="text-danger mb-2 ml-2">{{ err }}</small>
{% endfor %}
</td>
</tr>
这是 Javacript
<script>
const q=(e,n=document)=>n.querySelector(e);
const qa=(e,n=document)=>n.querySelectorAll(e);
const results={};
console. log(results)
qa('[type="number"].form-control').forEach(input=>input.addEventListener('input',function(e){
results[ this.name ]=Number( this.value );
const resultGroupSet1 = [...qa('.subtotal-group-1')]
.map(s => Number(s.value))
.reduce((a,v) => a+v);
q('th#Total').textContent = resultGroupSet1;
}));
</script>
这里是 HTML 模板
中反映总数的地方 <thead class="table-light">
<tr>
<th scope="col">Total Equipment and Assets</th>
<th scope="col" id="Total"></th>
</tr>
</thead>
这是models.py
item_1 = models.CharField(max_length=100,null=True, blank=True, verbose_name='Item 1')
item_1_amount = models.IntegerField(null=True, blank=True, verbose_name='Item 1 Amount')
item_2 = models.CharField(max_length=100,null=True, blank=True, verbose_name='Item 2')
item_2_amount = models.IntegerField(null=True, blank=True, verbose_name='Item 2 Amount')
total_assets = models.IntegerField(null=True, blank=True, verbose_name='Total Assets')
观点如下:
def add_bp(request):
if request.method == 'POST':
# create a form instance and populate it with data from the request:
form = infoForm(request.POST)
# check whether it's valid:
if form.is_valid():
form.save()
b_name = form.cleaned_data.get('bName')
messages.success(request, f'PDF created for {b_name}!')
return redirect('application:core')
# if a GET (or any other method) we'll create a blank form
else:
form = infoForm()
return render(request, 'application/template.html', {'form': form, })
我假设您的问题是如何获取此元素中的值:
<th scope="col" id="Total"></th>
您只需在 html 代码中添加输入元素并将名称添加到其中:
<th scope="col"><input id="Total" name="total_assets" value=""></th>
然后在你的 views.py:
def add_bp(request):
if request.method == 'POST':
form = infoForm(request.POST)
if form.is_valid():
form.save()
您也可以手动获取总数:
def add_bp(request):
if request.method == 'POST':
total_assets = request.POST.get("total_assets")
可能您要找的是 <input type="hidden" ...>
,最终用户看不到它,它包含在表单提交中
将html更新为:
<thead class="table-light">
<tr>
<th scope="col">Total Equipment and Assets</th>
<th scope="col">
<!-- Value which is visible (calculated using JS) -->
<span id="Total"></span>
<!-- Add a hidden input to store value (value calculated and assigned using JS) -->
<input type="hidden" name="total_assets" value="0" id="total_assets">
</th>
</tr>
</thead>
更新脚本以将 resultGroupSet1
分配为:
- 带有
id=Total
的 span 标签的文本内容
- 隐藏输入的值
name=total_assets
// Assign result to span tag which is visible
q('span#Total').textContent = resultGroupSet1;
// Assign result as value to hidden input field with name total_assets
q('input#total_assets').value = resultGroupSet1;
视图没有其他变化。
由于使用了带有 name="total_assets"
的输入字段,该值将被传递到请求正文,并且可以在 request.POST
处访问。在这里,由于 total_assets
字段是隐藏的,所以它对用户不可见,并且在提交表单时该值在 POST 数据中仍然可用。所以,当调用 form.save()
时,计算值(使用 JS)将被保存。
为什么不在 Django 后端进行这个计算?
我的建议是正常传递所有参数,只为模型保存添加一个监听器(每次你将一个元素保存到table这一小段代码将运行正确在保存之前):
from django.db.models.signals import pre_save
from django.dispatch import receiver
@receiver(pre_save, model_class)
def form_pre_save(instance, *args, **kwargs):
instance.total_assets = instance.item_1_amount + instance.item_2_amount
这样当您想将这种元素保存在不同的地方(例如在后端)时,您不必重新编写执行此操作的代码,而只需保存实例。
您可以阅读有关信号 pre_save 函数的更多信息 here