有两个提交的 Django 表单,不会响应我创建的文件
Django form with two submits, won't respond with the file I create
编辑:我在尝试单击“导出到 KML”按钮时在 Web 控制台中看到的错误:
VM211:1 Uncaught SyntaxError: Unexpected token < in JSON at position 0
at JSON.parse (<anonymous>)
at Object.success ((index):260)
at j (jquery.min.js:2)
at Object.fireWith [as resolveWith] (jquery.min.js:2)
at x (jquery.min.js:5)
at XMLHttpRequest.b (jquery.min.js:5)
javascript:
$('form').submit(function(e){
$.post('/swsite/globe/', $(this).serialize(), function(data){
//this
var json = JSON.parse(data);
var jsonf = JSON.parse(json.data);
var json2 = JSON.parse('{"foo" : "bar"}')
console.log(JSON.parse(data).data);
for(var i=0; i<jsonf.features.length; i++)
{
var entitycesium = new Cesium.Entity();
entitycesium.name = jsonf.features[i].properties.name;
entitycesium.polygon=new Cesium.PolygonGraphics({
hierarchy : Cesium.Cartesian3.fromDegreesArray([
jsonf.features[i].geometry.coordinates[0][0][0],jsonf.features[i].geometry.coordinates[0][0][1],
jsonf.features[i].geometry.coordinates[0][1][0],jsonf.features[i].geometry.coordinates[0][1][1],
jsonf.features[i].geometry.coordinates[0][2][0],jsonf.features[i].geometry.coordinates[0][2][1],
jsonf.features[i].geometry.coordinates[0][3][0],jsonf.features[i].geometry.coordinates[0][3][1],
jsonf.features[i].geometry.coordinates[0][4][0],jsonf.features[i].geometry.coordinates[0][4][1],
]),
outline:true,
outLineColor : Cesium.Color.RED,
material : Cesium.Color.GREEN.withAlpha(0.1),
});
//when sar processor builds out the json add in the deepviewerurl into it too and ready for loading into db.
//entitycesium.description= '<a href=\"' + jsonf.features[i].properties.file_name + '\" target="_blank">Full Resolution Viewer</a>';
entitycesium.description= '<a href=\"' + jsonf.features[i].properties.dzi_location + ' \" target="_blank">Full Resolution Viewer</a>' +
'<p> Country code ' + jsonf.features[i].properties.country_code + '</p>' +
'<p> Corner coords ' + jsonf.features[i].properties.corner_coords + '</p>' +
'<p> Sensor: ' + jsonf.features[i].properties.sensor + '</p>' +
'<p> Target: ' + jsonf.features[i].properties.targetName + '</p>' +
'<p> Collection Date: ' + jsonf.features[i].properties.collection_date + '</p>';
viewer.entities.add(entitycesium);
var numpoints=5;
for(var np =0; np<numpoints; np++)
{
// console.log(jsonf.features[i].geometry.coordinates[0][np]);
}
// console.log("BREAK");
}
//I really hate how the getById does nothing
var ev= viewer.entities;
viewer.flyTo(ev);
//jsonf.features[currentFeature].geometry.coordinates[0][0-5][0-2]
//console.log(jsonf.features[0].geometry.coordinates);
for(var i=0; i<ev.values.length; i++)
{
$('#entitylist').append('<option value ='+ ev.values[i].id +'> '+ ev.values[i].name + '</option>');
}
//$('.message').html(ev.values[0].id);
//$('.message').html(json.data);
});
e.preventDefault();
});
我不关心的是为什么浏览器会关心返回的是文件吗?
所以我终于让两个提交按钮工作了,然后我想我可以复制正确的代码并将其放在操作的正确部分。我的 views.py 这个动作看起来像:
def globe(request):
if request.method == 'POST':
form = EntityGlobeForm(request.POST)
#two submit butotns
#hidden_checkbox means they are interacting with the form
if request.POST.get('hidden_checkbox'):
#put items on the virtual globe
if form.is_valid():
#you are going to have to make a panel and paginate footprints
#object_list = ChangeDetectCSV.objects.filter(processing_level='RAW') #AND DATE
sensor = form.cleaned_data.get('layer') #it is really sensor
#if sensor is not
object_list = CesiumEntity.objects.filter(sensor = sensor)
jdata= serialize('geojson', object_list,
geometry_field='mpoly',
fields=('name','file_name', 'id', 'dzi_location', 'country_code', 'corner_coords', 'sensor', 'targetName', 'collection_date'))
return HttpResponse(json.dumps({'data': jdata}))
#the other means they clicked the download option instead
else:
# Create the HttpResponse object with the appropriate KML.
print 'building kml'
kml = simplekml.Kml()
kml.newpoint(name="Kirstenbosch", coords=[(18.432314,-33.988862)]) # lon, lat, optional height
response = HttpResponse(kml.kml())
response['Content-Disposition'] = 'attachment; filename="botanicalgarden.kml"'
response['Content-Type'] = 'application/kml'
print 'about to return response: ' + str(response)
return response
else:
form = EntityGlobeForm
return render_to_response('swsite/sw_nga_globe.html', {'form':form },
context_instance=RequestContext(request))
我在黑客攻击方面确实得到了一些帮助POST.get(模板代码在这里)
<form action="/" method="post" id="form">{% csrf_token %}
<!-- {{ form.as_table }} -->
<table>
{% for field in form %}
<tr><td><font color="white">{{field}}</font></td></tr>
{% endfor %}
</table>
<!-- input type="submit" name="LoadLayer" value="Load Entities" />
<input type="submit" name="notloadlayer" value="Export KML" / -->
<input type="checkbox" name="hidden_checkbox" id="hidden_checkbox" style="display:none"/>
<input type="button" value="Load Entities" data-action="true"/>
<input type="button" value="Export KML" data-action="false"/>
</form>
所以打印响应是 KML 文件,但它永远不会返回到浏览器,没有任何反应。我认为设置类型和配置会告诉浏览器正确的事情。我有通过 link 在它自己的操作中构建 KMl 的代码,它工作正常,现在将它填充到下面的其他操作代码中 (globe) 现在不起作用了吗?浏览器什么都不做,文件永远不会弹出下载甚至启动 google earth 就像它那样(因为它是一个 KML 文件)
从您的问题中,我们可以看出您的 javascript 正在尝试将某些文本解析为 JSON,但由于遇到无效字符 <
.[=23 而失败了=]
您的视图代码有两个分支,具体取决于 hidden_checkbox
值是否在提交的表单中。
如果 hidden_checkbox
存在,视图 return 是序列化为 JSON 的响应。
如果 hidden_checkbox
不存在,视图 return 是一些 kml;由于 kml 是一种 xml 方言,所以它类似于 <kml>...</kml>
.
您的 javascript 正在尝试将 kml 解析为 JSON,但失败了,因为 KML 无效 JSON。 (您可以通过在浏览器的 javascript 控制台中键入 JSON.parse('<kml></kml>')
来演示这一点 - 您会收到错误消息。)
我建议您在 javascript 中使用单独的事件处理程序,在 python 中使用两个单独的视图来处理两个提交按钮。
所以:
- 如果按下第一个按钮,该按钮的 javascript 事件处理程序提交 POST 请求,视图 returns JSON,javascript 解析 JSON 并执行它应该做的任何事情。
- 如果按下第二个按钮,该按钮的 javascript 处理程序会提交 POST 请求,视图 return 是 kml,javascript 不会尝试解析为 JSON 如果您的 headers 设置正确,下载应该会自动发生。
编辑:示例代码。
HTML
<form id="form" method="POST" action="/export-kml/">
{% csrf_token %}
<!-- Form fields here -->
<!-- Handle clicking on this button with javascript -->
<button type="button" value="Load Entities" data-action="/load-entities/">Load</button>
<!-- Let the browser handle clicks on this button -->
<button type="submit" value="Export KML">Export</button>
</form>
Django 浏览量
def globe(request):
"""Handles retrieving items to be displayed on the virtual globe."""
if request.method == 'POST':
form = EntityGlobeForm(request.POST)
#put items on the virtual globe
if form.is_valid():
#you are going to have to make a panel and paginate footprints
#object_list = ChangeDetectCSV.objects.filter(processing_level='RAW') #AND DATE
sensor = form.cleaned_data.get('layer') #it is really sensor
#if sensor is not
object_list = CesiumEntity.objects.filter(sensor = sensor)
jdata= serialize('geojson', object_list,
geometry_field='mpoly',
fields=('name','file_name', 'id', 'dzi_location', 'country_code', 'corner_coords', 'sensor', 'targetName', 'collection_date'))
return HttpResponse(json.dumps({'data': jdata}))
else:
form = EntityGlobeForm
return render_to_response('swsite/sw_nga_globe.html', {'form':form },
context_instance=RequestContext(request))
def export_kml(request):
"""Handles exporting KML file using information from the form."""
if request.method == 'POST':
form = EntityGlobeForm(request.POST)
# Create the HttpResponse object with the appropriate KML.
if form.is_valid():
print 'building kml'
kml = simplekml.Kml()
kml.newpoint(name="Kirstenbosch", coords=[(18.432314,-33.988862)]) # lon, lat, optional height
response = HttpResponse(kml.kml())
response['Content-Disposition'] = 'attachment; filename="botanicalgarden.kml"'
response['Content-Type'] = 'application/kml'
print 'about to return response: ' + str(response)
return response
else:
form = EntityGlobeForm
return render_to_response('swsite/sw_nga_globe.html', {'form':form },
context_instance=RequestContext(request))
javascript
$(document).ready(function () {
$('button[value="Load Entities"]').on('click', function () {
// Submit the form to the url defined in the button's data-action attribute.
console.log('Handling Loading Entities');
var form = $('#form');
$.ajax({
type: form.prop('method'),''
url: $(this).data('action'),
data: form.serialize(),
success: function (data) {
// Do something with the returned data.
console.log(data);
}
});
});
});
说明
我更改了表单,使其 action 属性指向处理 KML 导出的视图。 'Load Entities' 按钮被赋予了
data-action 属性指向处理 returning JSON 数据的视图(您必须更改这些 url 以匹配您的视图)。 'Export KML'
按钮的类型已更改为 submit,因此单击它会将表单提交到 KML 导出视图,而无需任何 javascript.
根据您问题中的代码,我简化了 globe
视图并添加了一个 export_kml
视图来处理导出 kml。现在我们正在使用两个
视图中不再需要 hidden_checkbox
逻辑(或在您的 javascript 中)。
您的 javascript 需要处理对 'Load Entities' 按钮的点击;我编写的 clickhandler 将表单提交到 globe
视图。
点击 'Export KML' 按钮由浏览器处理;这样,如果成功提交表单,KML 附件将是 return 并自动
由浏览器处理。处理 Ajax POST 请求中的附件非常棘手,最好让浏览器处理。
编辑:我在尝试单击“导出到 KML”按钮时在 Web 控制台中看到的错误:
VM211:1 Uncaught SyntaxError: Unexpected token < in JSON at position 0
at JSON.parse (<anonymous>)
at Object.success ((index):260)
at j (jquery.min.js:2)
at Object.fireWith [as resolveWith] (jquery.min.js:2)
at x (jquery.min.js:5)
at XMLHttpRequest.b (jquery.min.js:5)
javascript:
$('form').submit(function(e){
$.post('/swsite/globe/', $(this).serialize(), function(data){
//this
var json = JSON.parse(data);
var jsonf = JSON.parse(json.data);
var json2 = JSON.parse('{"foo" : "bar"}')
console.log(JSON.parse(data).data);
for(var i=0; i<jsonf.features.length; i++)
{
var entitycesium = new Cesium.Entity();
entitycesium.name = jsonf.features[i].properties.name;
entitycesium.polygon=new Cesium.PolygonGraphics({
hierarchy : Cesium.Cartesian3.fromDegreesArray([
jsonf.features[i].geometry.coordinates[0][0][0],jsonf.features[i].geometry.coordinates[0][0][1],
jsonf.features[i].geometry.coordinates[0][1][0],jsonf.features[i].geometry.coordinates[0][1][1],
jsonf.features[i].geometry.coordinates[0][2][0],jsonf.features[i].geometry.coordinates[0][2][1],
jsonf.features[i].geometry.coordinates[0][3][0],jsonf.features[i].geometry.coordinates[0][3][1],
jsonf.features[i].geometry.coordinates[0][4][0],jsonf.features[i].geometry.coordinates[0][4][1],
]),
outline:true,
outLineColor : Cesium.Color.RED,
material : Cesium.Color.GREEN.withAlpha(0.1),
});
//when sar processor builds out the json add in the deepviewerurl into it too and ready for loading into db.
//entitycesium.description= '<a href=\"' + jsonf.features[i].properties.file_name + '\" target="_blank">Full Resolution Viewer</a>';
entitycesium.description= '<a href=\"' + jsonf.features[i].properties.dzi_location + ' \" target="_blank">Full Resolution Viewer</a>' +
'<p> Country code ' + jsonf.features[i].properties.country_code + '</p>' +
'<p> Corner coords ' + jsonf.features[i].properties.corner_coords + '</p>' +
'<p> Sensor: ' + jsonf.features[i].properties.sensor + '</p>' +
'<p> Target: ' + jsonf.features[i].properties.targetName + '</p>' +
'<p> Collection Date: ' + jsonf.features[i].properties.collection_date + '</p>';
viewer.entities.add(entitycesium);
var numpoints=5;
for(var np =0; np<numpoints; np++)
{
// console.log(jsonf.features[i].geometry.coordinates[0][np]);
}
// console.log("BREAK");
}
//I really hate how the getById does nothing
var ev= viewer.entities;
viewer.flyTo(ev);
//jsonf.features[currentFeature].geometry.coordinates[0][0-5][0-2]
//console.log(jsonf.features[0].geometry.coordinates);
for(var i=0; i<ev.values.length; i++)
{
$('#entitylist').append('<option value ='+ ev.values[i].id +'> '+ ev.values[i].name + '</option>');
}
//$('.message').html(ev.values[0].id);
//$('.message').html(json.data);
});
e.preventDefault();
});
我不关心的是为什么浏览器会关心返回的是文件吗?
所以我终于让两个提交按钮工作了,然后我想我可以复制正确的代码并将其放在操作的正确部分。我的 views.py 这个动作看起来像:
def globe(request):
if request.method == 'POST':
form = EntityGlobeForm(request.POST)
#two submit butotns
#hidden_checkbox means they are interacting with the form
if request.POST.get('hidden_checkbox'):
#put items on the virtual globe
if form.is_valid():
#you are going to have to make a panel and paginate footprints
#object_list = ChangeDetectCSV.objects.filter(processing_level='RAW') #AND DATE
sensor = form.cleaned_data.get('layer') #it is really sensor
#if sensor is not
object_list = CesiumEntity.objects.filter(sensor = sensor)
jdata= serialize('geojson', object_list,
geometry_field='mpoly',
fields=('name','file_name', 'id', 'dzi_location', 'country_code', 'corner_coords', 'sensor', 'targetName', 'collection_date'))
return HttpResponse(json.dumps({'data': jdata}))
#the other means they clicked the download option instead
else:
# Create the HttpResponse object with the appropriate KML.
print 'building kml'
kml = simplekml.Kml()
kml.newpoint(name="Kirstenbosch", coords=[(18.432314,-33.988862)]) # lon, lat, optional height
response = HttpResponse(kml.kml())
response['Content-Disposition'] = 'attachment; filename="botanicalgarden.kml"'
response['Content-Type'] = 'application/kml'
print 'about to return response: ' + str(response)
return response
else:
form = EntityGlobeForm
return render_to_response('swsite/sw_nga_globe.html', {'form':form },
context_instance=RequestContext(request))
我在黑客攻击方面确实得到了一些帮助POST.get(模板代码在这里)
<form action="/" method="post" id="form">{% csrf_token %}
<!-- {{ form.as_table }} -->
<table>
{% for field in form %}
<tr><td><font color="white">{{field}}</font></td></tr>
{% endfor %}
</table>
<!-- input type="submit" name="LoadLayer" value="Load Entities" />
<input type="submit" name="notloadlayer" value="Export KML" / -->
<input type="checkbox" name="hidden_checkbox" id="hidden_checkbox" style="display:none"/>
<input type="button" value="Load Entities" data-action="true"/>
<input type="button" value="Export KML" data-action="false"/>
</form>
所以打印响应是 KML 文件,但它永远不会返回到浏览器,没有任何反应。我认为设置类型和配置会告诉浏览器正确的事情。我有通过 link 在它自己的操作中构建 KMl 的代码,它工作正常,现在将它填充到下面的其他操作代码中 (globe) 现在不起作用了吗?浏览器什么都不做,文件永远不会弹出下载甚至启动 google earth 就像它那样(因为它是一个 KML 文件)
从您的问题中,我们可以看出您的 javascript 正在尝试将某些文本解析为 JSON,但由于遇到无效字符 <
.[=23 而失败了=]
您的视图代码有两个分支,具体取决于 hidden_checkbox
值是否在提交的表单中。
如果 hidden_checkbox
存在,视图 return 是序列化为 JSON 的响应。
如果 hidden_checkbox
不存在,视图 return 是一些 kml;由于 kml 是一种 xml 方言,所以它类似于 <kml>...</kml>
.
您的 javascript 正在尝试将 kml 解析为 JSON,但失败了,因为 KML 无效 JSON。 (您可以通过在浏览器的 javascript 控制台中键入 JSON.parse('<kml></kml>')
来演示这一点 - 您会收到错误消息。)
我建议您在 javascript 中使用单独的事件处理程序,在 python 中使用两个单独的视图来处理两个提交按钮。
所以:
- 如果按下第一个按钮,该按钮的 javascript 事件处理程序提交 POST 请求,视图 returns JSON,javascript 解析 JSON 并执行它应该做的任何事情。
- 如果按下第二个按钮,该按钮的 javascript 处理程序会提交 POST 请求,视图 return 是 kml,javascript 不会尝试解析为 JSON 如果您的 headers 设置正确,下载应该会自动发生。
编辑:示例代码。
HTML
<form id="form" method="POST" action="/export-kml/">
{% csrf_token %}
<!-- Form fields here -->
<!-- Handle clicking on this button with javascript -->
<button type="button" value="Load Entities" data-action="/load-entities/">Load</button>
<!-- Let the browser handle clicks on this button -->
<button type="submit" value="Export KML">Export</button>
</form>
Django 浏览量
def globe(request):
"""Handles retrieving items to be displayed on the virtual globe."""
if request.method == 'POST':
form = EntityGlobeForm(request.POST)
#put items on the virtual globe
if form.is_valid():
#you are going to have to make a panel and paginate footprints
#object_list = ChangeDetectCSV.objects.filter(processing_level='RAW') #AND DATE
sensor = form.cleaned_data.get('layer') #it is really sensor
#if sensor is not
object_list = CesiumEntity.objects.filter(sensor = sensor)
jdata= serialize('geojson', object_list,
geometry_field='mpoly',
fields=('name','file_name', 'id', 'dzi_location', 'country_code', 'corner_coords', 'sensor', 'targetName', 'collection_date'))
return HttpResponse(json.dumps({'data': jdata}))
else:
form = EntityGlobeForm
return render_to_response('swsite/sw_nga_globe.html', {'form':form },
context_instance=RequestContext(request))
def export_kml(request):
"""Handles exporting KML file using information from the form."""
if request.method == 'POST':
form = EntityGlobeForm(request.POST)
# Create the HttpResponse object with the appropriate KML.
if form.is_valid():
print 'building kml'
kml = simplekml.Kml()
kml.newpoint(name="Kirstenbosch", coords=[(18.432314,-33.988862)]) # lon, lat, optional height
response = HttpResponse(kml.kml())
response['Content-Disposition'] = 'attachment; filename="botanicalgarden.kml"'
response['Content-Type'] = 'application/kml'
print 'about to return response: ' + str(response)
return response
else:
form = EntityGlobeForm
return render_to_response('swsite/sw_nga_globe.html', {'form':form },
context_instance=RequestContext(request))
javascript
$(document).ready(function () {
$('button[value="Load Entities"]').on('click', function () {
// Submit the form to the url defined in the button's data-action attribute.
console.log('Handling Loading Entities');
var form = $('#form');
$.ajax({
type: form.prop('method'),''
url: $(this).data('action'),
data: form.serialize(),
success: function (data) {
// Do something with the returned data.
console.log(data);
}
});
});
});
说明
我更改了表单,使其 action 属性指向处理 KML 导出的视图。 'Load Entities' 按钮被赋予了 data-action 属性指向处理 returning JSON 数据的视图(您必须更改这些 url 以匹配您的视图)。 'Export KML' 按钮的类型已更改为 submit,因此单击它会将表单提交到 KML 导出视图,而无需任何 javascript.
根据您问题中的代码,我简化了 globe
视图并添加了一个 export_kml
视图来处理导出 kml。现在我们正在使用两个
视图中不再需要 hidden_checkbox
逻辑(或在您的 javascript 中)。
您的 javascript 需要处理对 'Load Entities' 按钮的点击;我编写的 clickhandler 将表单提交到 globe
视图。
点击 'Export KML' 按钮由浏览器处理;这样,如果成功提交表单,KML 附件将是 return 并自动 由浏览器处理。处理 Ajax POST 请求中的附件非常棘手,最好让浏览器处理。