2016-12-29 44 views
0

編輯:錯誤我在Web控制檯中看到試圖單擊導出爲KML按鈕:Django的形式有兩個的提交,將無法與文件響應創建

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(模板這裏代碼)的hacerking

<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文件,但它永遠不會回到瀏覽器,沒有任何反應。我認爲設置類型和性格告訴瀏覽器正確的事情。我的代碼是通過鏈接調用自己的操作來構建KMl,它運行良好,現在將它填充到下面的其他操作代碼(globe)現在不起作用?瀏覽器什麼都不做,並且文件永遠不會彈出來下載,甚至不會像啓動谷歌地球一樣啓動谷歌地球(它是一個KML文件)

+0

如果您註釋掉這些打印語句,會發生什麼情況? – AMG

+0

我刪除了它們,但仍然無法使用。奇怪的是,它可能是我如何處理兩個提交按鈕......在Web控制檯中有一個錯誤,所以我正在更新我的問題以顯示該錯誤,這對我來說很奇怪,比如它的響應不好? – Codejoy

回答

1

從你的問題,我們可以看到你的JavaScript試圖解析一些文本爲JSON,但由於遇到無效字符而失敗,<

您的查看代碼有兩個分支,用於檢查hidden_checkbox值是否在提交表單中。

如果存在hidden_checkbox,視圖將返回序列化爲JSON的響應。

如果hidden_checkbox不存在,則視圖返回一些kml;因爲kml是一個xml方言,所以這將是類似於<kml>...</kml>

您的JavaScript正在嘗試將kml解析爲JSON,並且由於KML不是有效的JSON而失敗。 (你可以在瀏覽器的javascript控制檯輸入JSON.parse('<kml></kml>')來證明這一點 - 你會得到一個錯誤。)

我建議你在你的javascript中有單獨的事件處理程序,並在你的python中有兩個單獨的視圖來處理兩個提交按鈕。

所以:

  • 如果按下第一個按鈕,該按鈕的JavaScript事件處理程序提交POST請求,視圖返回JSON時,JavaScript解析JSON和做什麼它應該做的事。
  • 如果第二個按鈕被按下,那個按鈕的JavaScript處理程序提交POST請求,視圖返回kml,javascript不會嘗試解析爲JSON,並且如果您的標頭設置正確,下載應該會自動進行。

編輯:實施例的代碼。

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); 
      } 
     }); 
    }); 

}); 

說明

我已經改變了形式,使得其行動屬性指向處理KML出口的觀點。 'Load Entities'按鈕已被賦予 data-action屬性,該屬性指向處理返回的JSON數據的視圖(您必須更改這些url以匹配您的視圖)。 '導出KML' 按鈕的類型已更改爲提交,因此單擊該按鈕將將表單提交到KML導出視圖,而不需要任何JavaScript。

根據您問題中的代碼,我簡化了globe視圖並添加了一個export_kml視圖來處理導出kml。現在我們正在使用兩個 視圖,不再需要視圖(或JavaScript中)的hidden_checkbox邏輯。

你的javascript需要處理點擊'Load Entities'按鈕;我寫的clickhandler將表單提交到globe視圖。

點擊'導出KML'按鈕由瀏覽器處理;這樣,如果表單成功提交,則KML附件將被返回並自動由瀏覽器處理 。在Ajax POST請求中處理附件非常棘手,讓瀏覽器處理它是最好的。

+0

謝謝你,現在我重新思考這個問題。事件處理程序捕獲的是kml回來,它應該是解析json並遇到kml並死亡或類似的東西。我必須說,我不知道如何在同一個提交表單上調用兩個不同的視圖,例如您的建議狀態。此外,JavaScript中的事件處理程序現在已經在同一個表單上提交。我努力讓這兩個按鈕的形式相同,我的黑客沒有得到回報,因爲我需要diff處理程序。不知道如何去... – Codejoy

+0

其次,一個JavaScript事件處理程序看起來有什麼不同的文件下載?我想我想要的東西像$('form')。submit(function(e){和我想要一個不同的表單提交也許我可以問它在輸入按鈕中點擊哪一個?看到隱藏的數據值,如果它的一個,調用一個表單提交,如果另一個表單提交,如果另一個調用一個不同的呢?這看起來很亂,而且有更好的方法來做到這一點? – Codejoy

+0

@Codejoy我會在今天晚些時候添加一些處理程序代碼,該視圖的kml分支根本不使用表單中的任何字段 - 這是真實代碼中的情況嗎? – snakecharmerb

相關問題