2016-12-29 10 views
0

EDIT: Ошибка Я вижу в веб-консоли, пытаясь нажать кнопку Экспорт 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)) 

Я имел некоторую помощь здесь hacerking на этом 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 файл, но он никогда не возвращается в браузер, ничего не происходит. Я думал, что настройка типа и расположения подсказывает браузеру правильную вещь. У меня был этот код построения KMl в его собственном действии, вызванном через ссылку, он работал нормально, теперь его набивка в этом другом коде действий ниже (глобус) теперь не работает? Браузер ничего не делает, и файл никогда не появляется для загрузки или даже для запуска Google Earth, как это было (существа это KML-файл)

+0

Что произойдет, если вы закомментируете эти заявления печати? – AMG

+0

Я удалил их, но все равно не работает. В нечетном повороте это может быть то, как im манипулировать y двумя кнопками отправки ... есть ошибка в веб-консоли, поэтому я обновляю свой вопрос, чтобы показать эту ошибку, мне странно, как плохой ответ? – Codejoy

ответ

1

С вашего вопроса мы можем видеть, что ваш javascript пытается разобрать какой-то текст как JSON, но сбой, поскольку он встречает недопустимый символ, <.

Ваш код вида имеет две ветви, определяющие, находится ли значение hidden_checkbox в поданной форме.

Если присутствует hidden_checkbox, представление возвращает ответ, сериализованный как JSON.

Если hidden_checkbox нет, вид возвращает некоторый kml; поскольку kml - это диалект xml, это будет что-то вроде <kml>...</kml>.

Ваш javascript пытается проанализировать kml как JSON и не удается, поскольку KML недействителен JSON. (Вы можете продемонстрировать это, набрав JSON.parse('<kml></kml>') в javascript-консоль вашего браузера - вы получите сообщение об ошибке.)

Я бы предположил, что у вас есть отдельные обработчики событий в вашем javascript и два отдельных вида на вашем питоне для обработки две кнопки отправки.

Итак:

  • если первая кнопка нажата, 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> 

ДжангоПросмотров

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» изменила свой тип на submit, так что щелчок по нему отправит форму в экспортный вид KML без необходимости в javascript.

На основе кода в вашем вопросе я упростил вид globe и добавил вид export_kml, чтобы обрабатывать экспорт kml. Теперь, когда мы используем два вида , больше нет необходимости в логике hidden_checkbox в представлении (или в вашем javascript).

Ваш javascript должен обрабатывать клики по кнопке «Загрузить объекты»; обработчик кликов, который я написал, представляет форму globe.

Клики по кнопке «Экспорт KML» обрабатываются браузером; таким образом, если форма успешно отправлена, вложение KML будет возвращено и автоматически будет обработано . Обработка вложений в запросах AJAX POST довольно сложная, позволяя браузеру работать с лучшими.

+0

спасибо, что теперь это имеет смысл теперь, когда я переосмысливаю об этом. Обработчик событий - это захват, который возвращается kml, и его предполагается разбор json и встречается с kml и умирает или что-то подобное. Должен сказать, я не уверен, как иметь две кнопки в одной и той же форме отправки, которые вызывают два разных мнения, например, ваши предложения. Кроме того, обработчики событий в javascript, которые у меня есть, находятся на одной и той же форме submit. Я работал над тем, чтобы эти две кнопки были в одной и той же форме, мой хак не расплатился, потому что мне нужны обработчики diff. Не знаете, как это сделать ... – Codejoy

+0

Во-вторых, обрабатывает ли обработчик событий javascript какой-либо другой для загрузки файла? Я предполагаю, что мне нужно что-то вроде $ ('form'). Submit (function (e) {и я хочу, чтобы другая форма могла быть представлена, может быть, я могу спросить, какой из них нажимает кнопка ввода, видя значение скрытых данных, и если его , вызовите одну форму submit и если другой вызов другой - это кажется беспорядочным, и, как есть лучший способ сделать это? – Codejoy

+0

@Codejoy Я добавлю код обработчика позже сегодня, но сначала один вопрос. В вашем примере кода, ветвь kml в представлении вообще не использует никаких полей из формы - так ли это в вашем реальном коде? – snakecharmerb

 Смежные вопросы

  • Нет связанных вопросов^_^