Koszyk z ajaxem w Django

Na dhtmlgoodies.com pojawił się niedawno ciekawy skrypt koszyka ze wspomaganiem ajaxa i dhtml - informacje o skrypcie oraz demo. Skrypt wykorzystuje PHP lecz my nauczymy go pythona i django

  • Pobierz paczkę ze skryptem i rozpakuj do pustego katalogu
  • Tworzymy projekt djano o nazwie "shop" oraz aplikację o nazwie "basket"
django-admin.py startproject shop
python manage.py startapp basket
  • Utwórz w katalogu projektu katalog templates oraz katalog media na pliki statyczne.
  • Do katalogu templates przenieś fly-to-basket.html
  • Do katalogu media przenieś katalogi js i images
  • Edytuj fly-to-basket.html i przy wywołaniach grafik i plików JS dodaj na początku /site_media/, by uzyskać śieżki, przykładowo:
<script type="text/javascript" src="/site_media/js/ajax.js"></script>
<script type="text/javascript" src="/site_media/js/fly-to-basket.js"></script>
  • Edytuj urls.py do postaci:
from django.conf.urls.defaults import *

urlpatterns = patterns('',
(r'^admin/', include('django.contrib.admin.urls')),
(r'^/?$', 'shop.basket.views.show_basket'),
(r'^site_media/(.*)$', 'django.views.static.serve', {'document_root': '/ścieżka/do/katalogu/media'}),
)
Wstawiając własną ścieżkę do katalogu media. Jak widać pod główny URL podłączyliśmy funkcję show_basket aplikacji basket. Trzeba teraz umieścić odpowiedni kod w basket/views.py:
from django.shortcuts import render_to_response

def show_basket(request):
	return render_to_response('fly-to-basket.html')
Po uruchomieniu serwera:
python manage.py runserver 8080
I wejściu na główną stronę - http://localhost:8080/ powinniśmy zobaczyć nasz koszyk. Wszystko powinno działać poza zapamiętywaniem stanu koszyka po prawej stronie (efekty wizualne muszą działać)

Teraz trzeba nauczyć koszyk wysyłania danych tam gdzie trzeba. Edytuj media/js/fly-to-basket.js i zmień nazwy plików na:
var url_addProductToBasket = 'addProduct/';
var url_removeProductFromBasket = 'removeProduct/';
  • Przy okazji znajdź w tym pliku: img.src = 'images/remove.gif'; i zamień na img.src = 'site_media/images/remove.gif';
  • do urls.py dodaj dwie nowe reguły:
(r'^addProduct/$', 'shop.basket.views.addProduct'),
(r'^removeProduct/$', 'shop.basket.views.removeProduct'),
  • do views.py dodaj dwie nowe funkcje:
def addProduct(request):
	print request.GET['productId']
def removeProduct(request):
	print request.GET['productIdToRemove']
Odśwież stronę i kliknij na różne produkty, a potem zobacz co dzieje się w konsoli z działającym serwerem - wypisane zostaną tam numery ID produktów - oznacza to że wszystko działa, dane są przesyłane jak należy. request.GET['productId'] zawiera numer ID produktu gdyż skrypt JS przesyła pod podaną stronę (addProduct/) poprzez GET zmienną o nazwie "productId" przechowującą wspomniany numer ID.
By testowo uruchomić wyświetlanie stanu koszyka po prawej stronie stwórz szablon add.html o kodzie:
1|||Calendar|||50
A funkcję addProduct zmodyfikuj do postaci:
def addProduct(request):
	print request.GET['productId']
	return render_to_response('add.html')
Po oświerzeniu dodawanie produktów powinno powodować pojawianie się w zawartości koszyka produku o ID 1 (Calenda). Zgodnie z opisem skryptu nasz addProduct powinien wyświetlić łańcuch:
ID produktu|||nazwa produktu|||cena produktu
Teraz by to wszystko działało dane muszą być zapisywane, oraz musi być sposób na ich odczyt... baza danych. Potrzebujemy w najprostszym przypadku tabeli koszyka: id, id produktu
W przypadku bardziej realnego sklepu dojdzie jeszcze sprawa ID użytkownika, tabeli produktów itd., ale na razie to opuścimy.
  • W settings.py do INSTALLED_APPS dodaj 'shop.basket'
  • Zmodyfikuj basket/models.py do postaci:
from django.db import models

class Basket(models.Model):
    product_id = models.IntegerField()
  • Utwórz tabele za pomocą polecenia:
python manage.py syncdb
  • Teraz trzeba zaktualizować kod widoku by zapisywał i kasował dane z koszyka:
from django.shortcuts import render_to_response
from django.http import HttpResponse
from shop.basket.models import *

# take from the template/example
products = {
'1': ['Callendar', '50'],
'2': ['Shopping module', '250'],
'3': ['Menu package', '35'],
'4': ['Ajax package', '50'],
'5': ['Week planner', '60'],
'6': ['Forum package', '150'],
'7': ['HTML editor', '150'],
'8': ['CSS creator', '125']
}

def show_basket(request):
	return render_to_response('fly-to-basket.html')
def addProduct(request):
	product = Basket(product_id = int(request.GET['productId']))
	product.save()
	res = products[request.GET['productId']]
	return render_to_response('add.html', {'result': res, 'id': request.GET['productId']})
def removeProduct(request):
	# whe have only product id so we need to delete one entry that has it.
	Basket.objects.filter(product_id__exact=int(request.GET['productIdToRemove']))[0].delete()
	# JavaScript wants this
	return HttpResponse("OK")
Szablon add.html zmieniamy na:
{{ id }}|||{{ result.0 }}|||{{ result.1 }}
Dodanie produktu do koszyka zapisze go w bazie danych, usunięcie usunie. Powyższy przykład jest bardzo ograniczony, lista produktów z koszyka widoczna po prawej stronie strony zniknie po odświeżeniu - nie pobieramy jej z bazy danych. Oprócz tego wypadałoby mieć tabelę na produkty, rozróżnianie produktów/koszyków różnych użytkowników i wiele innych opcji...
RkBlog

Django, 14 July 2008

Comment article
Comment article RkBlog main page Search RSS Contact