如何将JavaScript对象插入Django JSONField



在我的django web应用程序中,我有两个页面-一个是用户填写名称、大小、图像的表单,并指定图像上某些兴趣点的名称。下一页显示该图像,并允许用户在顶部放置一些与兴趣点相对应的SVG圆,当用户提交时,我希望第一页的表单和图像上圆(兴趣点(位置的JSONField都保存到一个模型中。

目前,我的解决方案是一个包含第一个表单的页面,然后将整个表单传递到下一个页面。由于我不想让用户再看到那个表单,我把它放在一个隐藏的div中。我从表单中渲染图像,并使用JavaScript在用户点击的地方画圆圈。当按下提交按钮时,它会在脚本中运行一个函数,该函数第二次提交表单,但在提交之前会用所有圆的位置更新JSONField。

下面的代码一直工作到表单提交,但当我使用view2函数时,form.is_valid((总是返回false。我怀疑问题就在这里:

document.getElementById("id_spots"(.innerHTML=spots

我认为,由于Django表单字段是一个JSONField,我可以将innerHTML分配为我在JavaScript中创建的spots对象。如果我看一下这对HTML的影响,就会在spots文本区域框中插入[object object]。我也尝试过JSON.stringfy(spots(,但没有成功。

有人能发现这个问题吗?有没有更好的方法来分配JSONFiled的值以匹配django中的变量?

views.py

def view1(request):
if request.method == 'POST':
form = ImageForm(request.POST, request.FILES)
if form.is_valid():
b64Img = str(b64encode(form.files['img'].file.read()))[2:-1]
return render(request, 'my-app/view2.html', { 'form': form, 'base': base, 'my_img': b64Img })
else:
form = ImageForm()
return render(request, 'my-app/page1.html', { 'form':form, "base":base })
def view2(request):
if request.method == 'POST':
form = ImageForm(request.POST, request.FILES)
if form.is_valid():
form.save()
else:
form = DocumentsForm()
return render(request, 'my-app/page1.html', {'form':form, 'base':base})

型号.py

class MyImage(models.Model):
name = models.CharField(max_length=50)
width = models.CharField(max_length=10)
height = models.CharField(max_length=10)
spot_names = models.CharField(max_length=1000)
img = models.ImageField(default=None, upload_to='media/')
spots = JSONField(blank=True)

def __str__(self):
return self.name

forms.py

class ImageForm(ModelForm):
class Meta:
model = MyImage
fields = '__all__'

html/js

{% extends 'main/base.html' %}
{% block content %}
<div class="my-div">
<div>
<h1>Draw Dots!</h1>
<h3 id="spot-selection">Click Spot: </h3>
</div>
<form id="drawForm" enctype="multipart/form-data" method="POST" action="/my-app/view2/">
{% csrf_token %}
<div style="display: none;">
{{ form }}
</div>

<svg id="svg">
<image id="my-img" href="data:image/png;base64,{{ my_img }}"/>          
</svg>
<button typr="button" id="submit-img" style="width: 100px;">Submit</button>
</form>
</div>
{% endblock %}

{% block script_content %}
const spotNames = "{{ form.spot_names.value }}".split(",")
const width = {{ form.width.value }}
const height = {{ form.height.value }}
var spots = {}
this.window.addEventListener('DOMContentLoaded', (event) => {
const svgElem = document.getElementsByTagName("svg")
if (svgElem != undefined && svgElem.length != 0) {
const svg = svgElem[0]
const image = svg.firstChild
var i = 0
document.getElementById("spot-selection").innerHTML = "Click Spot: " + spotNames[i]

svg.onclick = function(event) {
if (i < spotNames.length) {
var newCircle = document.createElementNS('http://www.w3.org/2000/svg', 'circle')
let m = mousePositionSVG(event)
newCircle.setAttribute('cx', m.x)
newCircle.setAttribute('cy', m.y)
newCircle.setAttribute('r', '10')
newCircle.setAttribute('fill', 'red')
svg.append(newCircle)
spots[spotNames[i]] = [width*(m.x / document.getElementById("my-img").getBoundingClientRect().width), height*(m.y / document.getElementById("my-img").getBoundingClientRect().height)]
i++
if (spotNames[i] != undefined){
document.getElementById("spot-selection").innerHTML = "Click Spot: " + spotNames[i]
}else{
document.getElementById("spot-selection").innerHTML = "All Spots Clicked!"
}

}
}
document.addEventListener("keydown", function(event){
if (event.key == "Backspace" && i > 0){
const circles = document.querySelectorAll("circle")
circles[circles.length - 1].remove()
i--
document.getElementById("spot-selection").innerHTML = "Click Spot: " + spotNames[i]
}
})
}
document.getElementById("submit-img").onclick = function() {
if (document.getElementById("spot-selection").innerHTML == "All Spots Clicked!"){
document.getElementById("id_spots").innerHTML = spots
console.log({{ form.spots.value }})
document.getElementById("spotForm").submit()
}
}
})
function mousePositionSVG(e) {
let svg = document.querySelector('svg')
var p = svg.createSVGPoint()
p.x = e.clientX
p.y = e.clientY
var ctm = svg.getScreenCTM().inverse();
var p =  p.matrixTransform(ctm);
return p;
}
{% endblock %}

使用JSON.stringfy((实际上是正确的方法:

document.getElementById("id_spots").innerHTML = JSON.stringify(spots)

我认为这部分是错误的,因为我在提交表单时遇到了错误,而表单中唯一更改的部分是JSONField。事实上,错误似乎来自ImageField。事实证明,如果将一个表单作为上下文传递给另一个页面,ImageFields将不会被保留。

我已经发布了一篇关于ImageField问题的更相关的帖子,所以任何新的答案都应该重定向到这篇帖子:如何以多页形式将图像文件从一个页面传递到另一个页面(Django(

最新更新