Django i Ajax

0

Witam,

Jest to moje pierwsze podejście do problematyki Ajaxa w Pythonie. Niestety nie mogę napisać prostego działającego kodu. Tak więc prosba o pomoc. Tak to wyglada u mnie:

Mam taki oto url:
url(r'^ajax_test/', views.ajax_test, name='ajax_test')

Prościutki widok:

def ajax_test(request):
    response_data = {'english': 'have', 'polish': 'mieć', 'sentence': 'Alice has got a cat.'}
    return render(request, 'languages/ajax_test.html', response_data)

I szablon z js w jednym (oczywiście tylko w celach testowych):

<button>Klik</button>

<p>Przykładowy tekst</p>
<script>
	$(document).ready(function(){
		$('button').click(function(){
			$.ajax({
				type: 'POST',
				url: 'ajax_test/'
			}).done(function(data){
				alert('Ok: ' + data)
			}).fail(function(){
				alert('Error!')
			})
		})
	});
</script>

Finał jest taki, że kliknięcie w "button" kończy sie alertem z napisem "Error!" ;/

Konsola zwraca natomiast cos takiego:

[04/Jul/2016 20:21:35] "GET /static/js/languages/scripts.js HTTP/1.1" 304 0
Forbidden (CSRF token missing or incorrect.): /languages/ajax_test/ajax_test/
[04/Jul/2016 20:21:38] "POST /languages/ajax_test/ajax_test/ HTTP/1.1" 403 2311

Chciałbym zwrócić uwagę na drugą i trzecią linię: skąd po raz drugi w ścieżce "ajax_test"?

0

Metody ajax'owe musisz wyposażyć w obsługę tokenów csrf. Coś więcej na ten temat tutaj: http://stackoverflow.com/questions/6506897/csrf-token-missing-or-incorrect-while-post-parameter-via-ajax-in-django

0

Po 1 co zauważyłem, nie dajesz mu żadnych danych do ajaxa. (Przy url i type powinno być jeszcze data).
Po 2 jak jestes na stronie /languages/ajax_test to wpisanie 'ajax_test' w url w ajaxie, doda to do końca linku - dlatego masz podwójne (powinieneś wpisać np. '/languages/ajax_test')
Tak poza ,do stron wielojęzycznych w django, jest moduł i18 paterns.

0

O, akurat trafiłem na blogowy post jednego gościa odnośnie tego tematu. Rzuć okiem, może Ci się przyda: http://marcelli.ca/2016/07/01/ajax.html

0
liske1 napisał(a):

Po 1 co zauważyłem, nie dajesz mu żadnych danych do ajaxa. (Przy url i type powinno być jeszcze data).
Po 2 jak jestes na stronie /languages/ajax_test to wpisanie 'ajax_test' w url w ajaxie, doda to do końca linku - dlatego masz podwójne (powinieneś wpisać np. '/languages/ajax_test')
Tak poza ,do stron wielojęzycznych w django, jest moduł i18 paterns.

  1. Na razie nie chcę niczego przesyłać na serwer, chcę tylko pobrać stamtąd dane.
  2. Dzięki - prawidłowa ścieżka w pliku do obsługi Ajaxa po stronie js to "'/languages/ajax_test/".
  3. To nie jest aplikacja wielojęzyczna, ale aplikacja do nauki słówek języków, których sie uczę ;) (chcę ją przerobić z PHP na Django i tym samym poznać nieco Django).
0

Jednak nie wszystko jeszcze działa jak chcę. A chciałbym po prostu w okienku alert ujrzeć dane pobrane z serwera w formacie json, które docelowo będa przetwarzane przez kod js. Jak to zrobić? Bo w chwili obecnej skrypt zwraca mi cały kod strony, a chcę pobrać tylko tę przykładową zawartość słownika...

Jeszcze prościej: chcę, by została wyrenderowana cała strona oraz jednocześnie przesłane do skryptu js dane w formacie json.

0
twentieth napisał(a):

Jednak nie wszystko jeszcze działa jak chcę. A chciałbym po prostu w okienku alert ujrzeć dane pobrane z serwera w formacie json, które docelowo będa przetwarzane przez kod js. Jak to zrobić? Bo w chwili obecnej skrypt zwraca mi cały kod strony, a chcę pobrać tylko tę przykładową zawartość słownika...

Jeszcze prościej: chcę, by została wyrenderowana cała strona oraz jednocześnie przesłane do skryptu js dane w formacie json.

W views szukasz danych i nie zwracasz response_data tylko zmienną, która akurat tą daną przechowuje. Czyli np:
Mam 'have' i 'polnish' więc piszesz funkcję, która, przyjmuje 2 parametry - Słowo i na jaki język ma to zmienić, a następnie zwraca tylko słowo 'mieć' z twojego słownika, taki krótki przykład:

przetlumaczone_slowo = przetlumacz_slowo('have', 'polnish')
return render(,przetlumaczone_slowo) # tutaj pominalem kilka przecinków, które najprawdopodobniej sam dopiszes

Tylko musisz ajaxem wysyłać 2 zmienne: slowo i jezyk ( tak jak wyżej pisałem: 'data' )

0
liske1 napisał(a):
twentieth napisał(a):

Jednak nie wszystko jeszcze działa jak chcę. A chciałbym po prostu w okienku alert ujrzeć dane pobrane z serwera w formacie json, które docelowo będa przetwarzane przez kod js. Jak to zrobić? Bo w chwili obecnej skrypt zwraca mi cały kod strony, a chcę pobrać tylko tę przykładową zawartość słownika...

Jeszcze prościej: chcę, by została wyrenderowana cała strona oraz jednocześnie przesłane do skryptu js dane w formacie json.

W views szukasz danych i nie zwracasz response_data tylko zmienną, która akurat tą daną przechowuje. Czyli np:
Mam 'have' i 'polnish' więc piszesz funkcję, która, przyjmuje 2 parametry - Słowo i na jaki język ma to zmienić, a następnie zwraca tylko słowo 'mieć' z twojego słownika, taki krótki przykład:

przetlumaczone_slowo = przetlumacz_slowo('have', 'polnish')
return render(,przetlumaczone_slowo) # tutaj pominalem kilka przecinków, które najprawdopodobniej sam dopiszes

Tylko musisz ajaxem wysyłać 2 zmienne: slowo i jezyk ( tak jak wyżej pisałem: 'data' )

Nie zrozumieliśmy się. Tutaj to, do czego chcę wykorzyhstywać swoją aplikację, nie ma najmniejszego znaczenia. Dlatego posłużę się jeszcze prostszym przykładem:

  1. Mam url:
    url(r'^ajax_test/', views.ajax_test, name='ajax_test')
  2. Widok:
@csrf_exempt
def ajax_test(request):
   dane = {'imie': 'Adam'} #króciutki słownik
   return render(request, 'moje_szablony/ajax_test.html', {})
  1. I szablon 'ajax_test.html' z kodem js obsługującym żądania ajaxowe:
<html>
<head>
</head>
<body>
   <button>Klik</button>
   <script>
	$(document).ready(function(){
		$('button').click(function(){
			$.ajax({
				type: 'POST',
				url: '/ajax_test/'
			}).done(function(data){
				alert(data.imie) //tutaj chciałbym wyświetlić wyraz 'Adam' jako wartosć klucza 'imie' z widoku
			}).fail(function(){
				alert('Error!')
			})
		})
	});
</script>
</body>
</html>

Efektem powyższego kodu będzie wyświetlenie się pod adresem "/ajax_test/" strony z jednym przyciskiem. Poprzez każdorazowe wciśnięcie tego przycisku chciałbym uruchomić kod ajaxowy, który pobierze z serwera słownik "{'imie': 'Adam'}" i w formacie json prześle mi go do skryptu js, w którym chciałbym mieć dostęp do klucza "imie". Tak więc chciałbym, aby ta niesamowicie skomplikowana aplikacja ;) po wcisnięciu buttona wyświetliła mi alert z imieniem "Adam" :)

0

Po pierwsze musisz zwróci w widoku te dane, a obecnie zwracasz pusty słownik.. Poza tym jak jest zwrócić json to raczej należałoby to 'zrzutowć' do jsona - json.dumps(data)

0
mikajlo napisał(a):

Po pierwsze musisz zwróci w widoku te dane, a obecnie zwracasz pusty słownik.. Poza tym jak jest zwrócić json to raczej należałoby to 'zrzutowć' do jsona - json.dumps(data)

return render(request, 'languages/ajax_test.html', json.dumps({'imie': 'Adam'}))

Tak też próbowałem. Efektem jest wyświetlenie sie błędu:

Exception Type:	ValueError
Exception Value:	
dictionary update sequence element #0 has length 1; 2 is required

Co robię nie tak?

0
mikajlo napisał(a):

Po pierwsze musisz zwróci w widoku te dane, a obecnie zwracasz pusty słownik.. Poza tym jak jest zwrócić json to raczej należałoby to 'zrzutowć' do jsona - json.dumps(data)

return render(request, 'languages/ajax_test.html', json.dumps({'imie': 'Adam'}))

Tak też próbowałem. Efektem jest wyświetlenie sie błędu:

Exception Type:	ValueError
Exception Value:	
dictionary update sequence element #0 has length 1; 2 is required

Co robię nie tak? Z opisu błędu wynika, że funkcja render() spodziewa się innego argumentu niż "json.dumps({'imie': 'Adam'})".

0

W zasadzie powinieneś z tego widoku zwracać obiekt HttpResponse

response= HttpResponse(content_type="application/json")
response.content = json.dumps(data)
return response

Popatrz sobie tutaj na przykład. Można to sobie nawet uruchomić: http://code.runnable.com/VZrTb9MbaDkmtv6X/ajax-form-with-django-for-python

0
mikajlo napisał(a):

W zasadzie powinieneś z tego widoku zwracać obiekt HttpResponse

response= HttpResponse(content_type="application/json")
response.content = json.dumps(data)
return response

Popatrz sobie tutaj na przykład. Można to sobie nawet uruchomić: http://code.runnable.com/VZrTb9MbaDkmtv6X/ajax-form-with-django-for-python

Tego sposobu też próbowałem. Wynikiem są surowe dane wyświetlone w oknie przeglądarki, w tym przypadku "{imie": "Adam"}". A gdzie miejsce na cały kod html z szablonu, który ma zostać wyrenderowany?

0

Dla JSONa nie ma potrzeby używania HttpResponse, skoro mamy JsonResponse ;-)

0

Dziękuję wszystkim za zaangażowanie. Już wiem, jak to wszystko działa :) Trzeba zmodyfikować nieco widok:

@csrf_exempt
def ajax_test(request):
   dane = {'imie': 'Adam'}
   if request.is_ajax():
      return JsonResponse(dane)
   else:
      return render(request, 'moje_szablony/ajax_test.html', {})

Funkcja render() w standardowy sposób wyświetla szablon, natomiast gdy strona jest już załadowana i klikam w button, obiekt JsonResponse za pomocą Ajaxa zwraca mi dane, które chcę :)

1 użytkowników online, w tym zalogowanych: 0, gości: 1