Как заставить POST-запрос при сохранении модели?

Мне нужно сделать POST для API на стороне сервера. Я должен отправить id введите тело запроса к серверу.

Я использую модель Backbone. Но, когда я делаю:

myModel.set("id", somevalue)    
myModel.save()

Запущенный сетевой запрос: URL/someValue [PUT]

Backbones не делает POST, а PUT и добавляет идентификатор в URL.

Так что я просто хочу передать id ключ к серверу без замечаний Backbone.

1 ответ

Решение

Из документа Backbone:

Backbone предварительно настроен для синхронизации с RESTful API.

[...]

По умолчанию sync обработчик отображает CRUD в REST примерно так:

  • создатьPOST /collection
  • читатьGET /collection[/id]
  • обновитьPUT /collection/id
  • патчPATCH /collection/id
  • удалитьDELETE /collection/id

Новая запись не имеет идентификатора, поэтому, если вы передадите ID модели перед ее сохранением, Backbone по умолчанию отправит запрос PUT, потому что думает, что вы хотите сохранить существующую запись.

Как сделать POST-запрос с идентификатором?

Выберите одно из следующих решений.

Придерживайтесь RESTful API

Этот является очевидным. Если можете, придерживайтесь стандарта.

Измените API для обработки запросов PUT/PATCH и используйте POST только при создании. Заставьте конечную точку API взять идентификатор из URL.

Лучшие практики API RESTful

Пройти type вариант 1

Просто и работает очень хорошо для одноразовой ситуации.

Все варианты переданы save (или же fetch) переопределяет параметры sync функция определяет по умолчанию и переходит к jQuery.ajax функция

позвоночник sync источник

// Make the request, allowing the user to override any Ajax options.
var xhr = options.xhr = Backbone.ajax(_.extend(params, options));
var url = model.url(); // get the url before setting the `id`
model.save({ 
    id: somevalue 
}, { 
    url: url, // fix the url
    type: 'POST' // choose the HTTP verb
});

Исправить URL, который использует модель, просто, у вас есть несколько вариантов:

  • пройти url вариант (как выше)
  • переопределить url функция модели

Переопределение url Функция ( источник) хорошо работает для ситуации, когда каждый вызов должен использовать определенный URL, без значения по умолчанию id добавлен к нему.

var MyModel = Backbone.Model.extend({
    url: function() {
        return _.result(this, 'urlRoot') ||
            _.result(this.collection, 'url') ||
            urlError();
    }
});

Установить idAttribute на модели

Это зависит от того, что id Вы пытаетесь передать средства в данных.

Магистральная модель использует "id" имеет имя атрибута идентификатора по умолчанию. Вы можете указать другое имя, переопределив idAttribute свойство модели. Независимо от названия, оно всегда автоматически доступно через model.id собственность

Теперь, предполагая id Атрибут не связан с этой моделью, и настоящее имя атрибута id этой модели UID Вы могли бы изменить idAttribute модели для отражения реального имени атрибута (или это может быть даже строка, которая никогда не будет атрибутом).

var MyModel = Backbone.Model.extend({
    idAttribute: 'UID',
});

Теперь id атрибут не считается идентификатором для текущей модели, и model.isNew() вернусь true, отправив запрос POST, чтобы создать его при сохранении.

Изменить sync / save функциональное поведение

Если используемый вами API не является RESTful, вы можете настроить поведение, переопределив sync функция Это может быть сделано на модели или коллекции, или на Backbone.sync функция, которая используется по умолчанию коллекциями и моделями.

Например, если вы хотите, чтобы каждый запрос использовал POST по умолчанию для MyModel учебный класс:

var MyModel = Backbone.Model.extend({
    sync: function(method, model, options) {
        return Backbone.sync.call(this, method, model,
            _.extend({ type: 'POST' }, options));
    }
});

Вы можете сделать что-то подобное только с save функция, чтобы позволить fetch сделать свое GET запрос как обычно.

Использовать emulateHTTP настройка 2

Если вы хотите работать с устаревшим веб-сервером, который не поддерживает стандартный подход REST/HTTP от Backbone, вы можете включить его. Backbone.emulateHTTP, Установка этой опции будет подделкой PUT, PATCH а также DELETE запросы с HTTP POST, установив X-HTTP-Method-Override заголовок с истинным методом.

[...]

Backbone.emulateHTTP = true;

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

Не переопределять isNew

Эта модель уже сохранена на сервере? Если модель еще не имеет идентификатора, она считается новой.

Некоторые другие ответы на этом сайте предлагают переопределить isNew функция Не Функция имеет свою цель, и ее переопределение для принудительной отправки POST-запроса - плохой взлом, а не решение.

isNew используется внутри, но также может использоваться вашим кодом или другими библиотеками и плагинами Backbone.


1 Хотя я не брал это из-за переполнения стека, это был уже ответ Андреса Торреса Маррокина на похожий вопрос.

2 Взято из ответа Maanas Royy.

Другие вопросы по тегам