У меня есть следующий код, который извлекает значения из простой формы ввода 3:

//retrieves data from a form
var $form = $( this ),
    prgname= $form.find('input[name="prg"]').val(),
    startDate = $("#startdate").datepicker({ dateFormat: 'yy-mm-dd' }).val(),
    endDate = $("#enddate").datepicker({ dateFormat: 'yy-mm-dd' }).val();

Следующий код отправляет запрос на сервер:

var request = $.ajax({
      url: "/prg/",
      type: "post",
  data: JSON.stringify({prg:  prgname, start:startDate, end:endDate}),
  contentType: 'application/json',
  dataType: 'json',
      success: function() {},
      error: function (jqXHR, textStatus, errorThrown){};

На стороне сервера, используя python и webapp2, я делаю следующее (вот где я не уверен в вещах)

import json

class PrgHandler(webapp2.RequestHandler):
    def post(self):
        prg= cgi.escape(self.request.POST['prg'])
        start_date = cgi.escape(self.request.POST['start'])
        end_date = cgi.escape(self.request.POST['end'])

        #some code to write to db here
        ....
        #if successful return a success message
        if success:
            success_msg = [{'class': 'success', 'msg': 'Successfully saved to the database'}]
        else:
            success_msg = [{'class': 'error', 'msg': 'Could not saved to the database'}]

        data_string = json.dumps(success_msg)
        self.response.headers.add_header('content-type', 'application/json', charset='utf-8')   
        self.response.write(data_string)

Когда я получаю ответ, он пропускает функцию успеха и переходит непосредственно к ошибке.

Регистрируя значения ошибок, я не получаю ничего значимого:

the error is:
The text status is:error
The jqXHR is:[object Object] 

Консоль Chrome выдаёт мне ошибку:

Resource interpreted as Document but transferred with MIME type application/json:

Я посмотрел, и решения на SO не работали, я думаю, что это ошибка с кодом на стороне сервера:

self.response.headers.add_header('content-type', 'application/json', charset='utf-8')

Если я закомментирую вышеприведенную строку, я не получаю сообщение об ошибке в Chrome и просто получаю ответ на пустой странице с правильными значениями в следующем формате:

[{"msg": "Successfully saved to the database", "class": "success"}]

В приведенном выше случае это сохраняет в базе данных, поэтому я не могу найти ничего плохого, кроме заголовка и просто не знаю, как действовать!

< Сильный > ИЗМЕНИТЬ Ошибка, похоже, со стороны сервера, я удалил следующую строку: event.preventDefault ( ) ;

Из моего сценария, и это вызвало все проблемы, теперь, по крайней мере, я получаю четкое указание на то, где проблема. Это из-за неправильного получения опубликованных данных, как бы я сделал это правильно? Я попробовал следующее:

json_data = self.request.GET.items()
decoded = json.loads(json_data)

Но я получаю TypeError: ожидаемую строку или буфер на следующей строке: json_data = self.request.GET.items ()

2
Tkingovr 25 Янв 2013 в 15:22

2 ответа

Лучший ответ

Итак, мне удалось выяснить это и подумать, что я опубликую ответ, который помог мне найти нужную информацию, потому что документы webapp2 не очень полезны, когда дело доходит до «получения» опубликованных данных json.

На стороне клиента я сделал следующее:

var request = $.ajax({
    url: "/some/url/",
    type: "POST",
    data: JSON.stringify([{someval: val1, someval2:val2, someval3:val3}]),
    contentType: "application/json",
    dataType: 'json',
    beforeSend: function() {
        $('#loading-div').show();
    },
    complete: function(){
        $('#loading-div').hide();
    },
    success: function(response, textStatus, jqXHR){}
});

Причина, по которой я не смог сразу выяснить проблему, заключалась в том, что я удалил следующую строку вместе с закомментированной строкой, которая препятствовала перенаправлению страницы после публикации. Это было источником всех странных, не связанных и бесполезных сообщений об ошибках:

event.preventDefault();

На стороне сервера, чтобы получить данные JSON, публикуемые в appengine, выполните следующие действия:

jdata = json.loads(cgi.escape(self.request.body))
    for vals in jdata:
        val1 = vals['someval']
        val2 = vals['someval2']
        val3 = vals['someval3']

Выше было основание проблемы, я не делал это правильно, и без предыдущей строки на стороне клиента не было никакого способа понять это.

В любом случае, когда у вас есть данные, выполняйте любую необходимую вам обработку, а когда вы закончите и должны отправить ответ json, добавьте следующие строки:

//the data would look something like this 
data = {'return_value': val1, 'return_value2': val2,
        'return_value3': val3, 'return_value4': val4}

        return_data = json.dumps(data)
        self.response.headers.add_header('content-type', 'application/json', charset='utf-8')
        self.response.write(return_data)

Почти забыл на стороне клиента снова получить доступ к переменным, отправленным обратно с сервера с помощью jquery, это очень просто ... сделать что-то вроде:

 success: function(response, textStatus, jqXHR){
        console.log(response.return_value);
        console.log(response.return_value2);
        console.log(response.return_value3);
 }

Надеюсь, что это поможет кому-то, ищущему эту информацию.

3
Tkingovr 29 Май 2013 в 15:47

Загляните в свой отладчик. Вы получаете JSON-строку в своем посте (webapp2 multidict). Вы должны декодировать эту строку, используя json.loads, в результате получается объект python.

Вот мой код jquery для отправки и получения json:

function gaeQuery(request) {
    var url = "/query";
    var payload = {'jsondata' : JSON.stringify(request)};
    $.post(
    url, 
    payload, 
    function(response) {
        procesResponse(response);
    },  // succes response callback 
    'json',  // response contains JSON content, and will be decoded in a js object
    {
        contentType: "application/json;charset=utf-8", // send JSON content
        timeout: 20000,
        tryCount: 0,
        retryLimit: 3, // max 3 retries             
        error: function(xhr, textStatus, errorThrown) { // error handling callback
            if (textStatus === 'timeout') {
                this.tryCount++;
                if (this.tryCount <= this.retryLimit) { //try again until retryLimit
                    $.ajax(this);
                    return;
                }
                alert('We have tried ' + this.retryLimit + ' times and it is still not working. We give in. Sorry.');
                return;
            }
            if (xhr.status === 500) { // internal server error
                alert('Oops! There seems to be a server problem, please try again later.');
            } 
            else {
                alert('Oops! There was a problem, sorry.'); // something went wrong
            }
        }
    }
    );
}
4
voscausa 25 Янв 2013 в 11:57