2012-08-30 11 views
5

Jestem nowy w Backbone.js i próbuję zapisać instancję modelu. Używam django jako mojego serwera.Zapisywanie danych modelu Backbone.js. Dane nieprzesyłane poprawnie

Client Code strona:

var Song = Backbone.Model.extend({ 
    defaults: { 
     name: 'New Song' 
    }, 
    url: function() { 
     return window.location.href; 
    } 

}); 

var song = new Song() 
song.save() 

csrfmiddlewaretoken jest ustawiony prawidłowo, zanim dane zostaną wysłane.

Przeszedłem przez funkcję jQuery $ .ajax wywołaną wewnętrznie przez Backbone.sync i odkryłem, że obiekt modelu zawiera poprawne dane.

Jednak request.POST otrzymanych przez serwer jest

POST:<QueryDict: {u'[object Object]': [u'']}> 

zamiast rzeczywistych danych. Każdy pomysł, gdzie idę źle?

Aktualizacja: Szybko naprawiłem, ustawiając wartość Backbone.emulateJSON na wartość true. Ale zgodnie z komentarzami w kodzie szkieletowym (0.9.2) jest on przeznaczony dla starszych serwerów. Używam Django 1.4.1. Czy to oznacza, że ​​django 1.4.1 jest niekompatybilny?

Aktualizacja 2: Kiedy ustawiony Backbone.emulateJSON do false, pojawia się następujący błąd w Firefoksie, ale nie cicho w chromie.

"[Exception... "Component returned failure code: 0x80460001 
(NS_ERROR_CANNOT_CONVERT_DATA)" nsresult: "0x80460001 (NS_ERROR_CANNOT_CONVERT_DATA)" 

    location: "JS frame :: http://localhost:8000/static/jquery.js :: <TOP_LEVEL> :: line 8214" data: no]" 

używam jQuery dla ajax jako preferowane przez Backbone i wydaje się, że błąd może być w jQuery.

Aktualizacja 3: Rozwiązałem to przez przesłonięcie $ .ajax używanego przez Backbone.sync z własnym. To wciąż jest szybkie rozwiązanie.

backbone.js verson: 0.9.2

wersja jQuery: 1.8.0. Próbowano także z wersją 1.7.2. Ten sam wynik.

+0

Czy można spojrzeć na panelu sieci i zobaczyć dane, które są publikowane na serwerze. Nie jestem zaznajomiony z Django, ale twój problem zdecydowanie wygląda na problem z serwerem, a nie problem z Backbone. – TYRONEMICHAEL

+0

@TyroneMichael Dzięki za sugestię. Panel sieci w chrome pokazuje, że model jest wysyłany jako zwykły obiekt w żądaniu ładunku. Ale w firefox dostałem błąd napisany w aktualizacji 2. – Pramod

+0

Nie sądzę, dane są wysyłane w postaci ciągów (Spójrz [tutaj] (http://communities.rightnow.com/posts/9580c78607)). Czy pojawia się ten błąd, gdy emulacja JSON ma wartość false? Co dzieje się w FF podczas komentowania Emuluj JSON = false? – TYRONEMICHAEL

Odpowiedz

9

Miałem podobny problem i dzięki pracy detektywa/szczęścia znalazłem to. Problem polega na tym, że domyślnie Backbone wysyła dane POST jako zakodowany ciąg JSON w treści żądania, a nie jako część QueryDict request.POST. Aby uzyskać dane w tym przypadku, trzeba użyć biblioteki json Pythona i zadzwonić pod numer json.loads(request.body) w widoku Django, aby odczytać dane poprawnie.

Na marginesie, ustawienie Backbone.emulateJSON = true; działa, ponieważ wtedy Backbone wysyła JSON do Django poprzez mechanizm "starszej wersji", który sprawia, że ​​pojawia się on w QueryDict request.POST.

+0

... lub 'json.loads (request.raw_post_data)' dla starszych wersji django –

1

Jeśli chcesz, aby dane były dostępne w żądaniu QueryDict.POST, musisz zastąpić metodę Backbone.sync.

Przede wszystkim musisz ustawić Backbone.emulateJSON na true.

Możesz rzucić okiem na metodę Backbone.sync ponad here. Zauważysz, że atrybuty modelu są uszeregowane.

if (options.data == null && model && (method === 'create' || method === 'update' || method === 'patch')) { 
    params.contentType = 'application/json'; 
    params.data = JSON.stringify(options.attrs || model.toJSON(options)); 
} 

Edycja ta część funkcji do:

if (options.data == null && model && (method === 'create' || method === 'update' || method === 'patch')) { 
    params.contentType = 'application/json'; 
    if(options.emulateJSON){ 
    params.data = options.attrs || model.toJSON(options); 
    }else{ 
    params.data = JSON.stringify(options.attrs || model.toJSON(options)); 
    } 
} 

Na innej linii można zauważyć, że Backbone dodaje klucz „model” na stanowisko QueryDict.

params.data = params.data ? {model: params.data} : {}; 

tej linii:

params.data = params.data ? params.data : {}; 

to wszystko! Teraz będziesz mieć dane jako część request.POST QueryDict.

Powiązane problemy