2

我正在使用后端的 Django 和前端的 Backbone.js 构建一个 Web 应用程序

当我尝试从服务器获取数据时,我遇到了 IE 问题。当我在 IE 中运行我的 HTML 页面时,集合获取总是调用错误函数。

我的代码:

$(function(){

var Chapter = Backbone.Model.extend({});

var Chapters = Backbone.Collection.extend({
    model: Chapter,
    url: 'http://ip.olya.ivanovss.info/chapters'
});

var chapters = new Chapters();

var Router = new (Backbone.Router.extend({
    routes: {
        "": "choose_activity",
        "/": "choose_activity"
    },

    choose_activity: function () {
        chapters.fetch({
            success: function () {
                AppView.render();
            },
            error: function() {
                alert('error');
            }
        });
    }
}))();

var AppView = new (Backbone.View.extend({
    el: '.popup',
    templates: {
        choose_activity: Handlebars.compile($('#tpl-activities').html())
    },
    render: function () {
        this.$el.html(this.templates["choose_activity"]({ chapters: chapters.toJSON()}));
    }
}))();

Backbone.history.start();
});

姜戈的观点:

def chapters(request):
    chapters = list(Chapter.objects.order_by('id'))
    response = HttpResponse(json.dumps(chapters, default=encode_myway), mimetype='text/plain')
    if request.META.get('HTTP_ORIGIN', None) in ('http://localhost', 'http://html.olya.ivanovss.info', 'http://10.0.2.2'):
        response['Access-Control-Allow-Origin'] = request.META['HTTP_ORIGIN']
    return response

先感谢您

4

1 回答 1

1

IE7 不支持 CORS。

有两种方法可以解决这个问题。简单的方法是通过您的 API 代理。我的 Python 生锈了(我是一名 Node/PHP 开发人员),但我确信有一百万零一个资源来说明如何做到这一点。这样做的好处是您不必接触 API。但这意味着您的本地服务器必须 CURL 并从您的 API 服务器返回每个请求。

第二个(和更少的服务器密集型方式)是 JSONP!JSONP 的想法是它<script>使用您指定的 URL 将 a 附加到文档中。jQuery 附加一个?callback=jQueryNNNwhereNNN是一个随机数。<script>加载时非常有效,它调用jQueryNNN('The Response Text')并且 jQuery 知道从那里解析响应。这样做的坏处是您必须在 API 端包装所有响应(如果您刚刚开始,这非常容易,如果您已经构建了基础架构,则不那么容易)。

JSONP 的烦人之处在于,从本质上讲,您不能执行 POST/PUT/DELETE。但是,如果您有权访问 API,则可以模拟它:

Backbone.emulateHTTP = true;

model.save();  // POST to "/collection/id", with "_method=PUT" + header.

将 JSONP 与 Backbone 集成非常简单(小秘密 Backbone.sync 使用 jQuery$.ajax()并且选项参数转发到 jQuery ;))。

对于访问交叉源的每个模型/集合,您可以添加一个 su

var jsonpSync = function (method, model, options) {
    options.timeout = 10000; // for 404 responses
    options.dataType = "jsonp";
    return Backbone.sync(method, model, options);
};

在每个集合和模型中,跨域是什么:

var MyCollection = Backbone.Collection.extend({
    sync  : jsonpSync
});

或者只是覆盖整个主干同步

Backbone.__sync = Backbone.sync;

var jsonpSync = function (method, model, options) {
    options.timeout = 10000; // for 404 responses
    options.dataType = "jsonp";
    return Backbone.__sync(method, model, options);
};

Backbone.sync = jsonpSync;

在服务器端,您可以执行以下操作:返回JSONP 响应(复制粘贴到此处):

def randomTest(request):
    callback = request.GET.get('callback', '')
    req = {}
    req ['title'] = 'This is a constant result.'
    response = json.dumps(req)
    response = callback + '(' + response + ');'
    return HttpResponse(response, mimetype="application/json")
于 2013-02-14T16:19:44.280 回答