Kurs Django Podstawa – #4 – Koszyk – Formularz
Posted on: August 7, 2024

Kurs Django Podstawa – #4 – Koszyk – Formularz
“Koszyk Formularz”
Celem tego rozdziału jest kolejna rozbudowa naszej strony (zobacz rozdział #3 Django). Będziemy chcieli dodać interaktywną funkcjonalność w postaci koszyka w naszym sklepie, który wyświetli nam w formie podsumowania wszystkie produkty, które chcemy kupić.
Najpierw musimy stworzyć przy każdym produkcie opcję dodaj do koszyka, potem zarezerwować odpowiednie miejsce w bazie danych na nasz koszyk, następnie spróbować jakoś wyświetlić zawartość koszyka w oddzielnej podstronie. Aby wykonać powyższe operacje, wykorzystamy znany Tobie pewnie formularz, a więc do dzieła!!!
Najpierw zaktualizujemy klasę Produkt o dodatkowy parametr liczba sztuk w koszyku - np. dodane.
Ta linijka dodaje nam nowy atrybut typu Integer (liczby całkowite, mogą być ujemne, ale na razie się tym nie przejmujmy) i ustawia go domyślnie na zero, żeby na starcie koszyk był pusty. Proste prawda ;D

Aby zaakceptować zmiany w pliku models.py, klepiemy standardowe dwa kody w konsoli, pamiętając o tym, że serwer jest wyłączony, ale aktywne jest środowisko wirtualne (nazwa w konsoli jest w nawiasach).
Włączamy serwer jako admin i widzimy dodatkowe okienko Dodane dla każdego obiektu klasy Produkt, ustawione domyślnie na zero.

Teraz dodamy okienko do wpisania ilości produktów i przycisk dodaj do koszyka w interfejsie naszej aplikacji.
Najpierw zaimplementujemy (ciekawe słowo zamiast napiszemy kod xP) formularz, aby to zrobić, potrzebujemy utworzyć nowy plik forms.py w naszym folderze Sklep (w folderze z plikiem models.py)

Teraz zdefiniujmy nasz formularz, korzystając z modelu Produkt i chcemy mieć możliwość wpisania ilości sztuk dodanych do koszyka, zmieniając atrybut dodane.
Model to klasa, do której ma się odwołać formularz, czyli w naszym przypadku Produkt,
a w fields i labels informujemy Django o atrybucie, w naszym przypadku dodane.

Potem wprowadzamy nowy adres URL, pod którym wykona się nasz kod z formularzem. Chcemy zdobyć informację o konkretnym produkcie i jego ilości w koszyku, więc informujemy Django, że adres URL zapyta też o numer ID produktu.

Teraz piszemy naszą funkcję w pliku views.py, na początku pliku dopisujemy
Żeby plik views.py miał źródło danych o formularzu, który zdefiniowaliśmy wcześniej.

Piszemy funkcję dodajkoszyk.
Pobieramy obiekt z danym id (podany w adresie URL), przypisujemy go w formularzu tak, żeby wyświetlał domyślnie wartość zero dla pustego pola oraz zostawił wpisaną wartość po wysłaniu formularza (gdy zapytanie jest POST) i jeśli zostały wypełnione wszystkie okienka formularza, jest walidacyjny (poprawny), zapisał formularz. Potem Django ma zapakować dane i wyświetlić nam stronę produkt.html.

Aktualizujemy plik produkt.html o formularz, uwzględniamy, że adres ma się odwołać do konkretnego produktu (obiektu klasy Produkt), Django, wie, że produkt.id to numer id produktu, no właśnie wie?

Jako że chcemy, aby formularz był widoczny z poziomu danego produktu, musimy zdefiniować formularz w funkcji produkt w pliku views.py o dodatkowe linie
i uwzględnić to przy wysyłaniu danych

Już mamy poprawnie działającą funkcję dodajkoszyk, która daje nam informację o chęci zakupu danej ilości produktów i przechowuje ją w bazie danych. Żeby ją aktywować, musimy kliknąć w dany produkt, czyli aktywować funkcję produkt z konkretnym id, w ten sposób w otrzymanej odpowiedzi od Django, będzie tam czekał również dodany formularz, który wykorzystuje ten sam numer id produktu.

Po kliknięciu przycisku dodaj do koszyka (aktywujemy funkcję dodajkoszyk), zmieni nam się wartość dodane w bazie danych z 0 na 5

Teraz zabierzmy się za wyświetlenie zawartości koszyka na oddzielnej stronie.
Stwórzmy podstronę koszyk.html, która wyświetli napis “Koszyk jest pusty jak słoik po ogórkach” i sprawmy, żeby była dostosowana do obecnej struktury, czyli żeby wyświetlała się jako 3 nagłówek obok Strona główna oraz Pokaż mi swoje towary.
Aktualizujemy plik szablon.html o nowy odnośnik, pod którym chowa się adres URL /koszyk

następnie plik urls.py

W pliku views.py dodajemy póki co funkcję koszyk, która wyświetli tylko plik koszyk.html.

i dodajmy plik koszyk.html
Twój koszyk jest pusty jak słoik po ogórkach
{% endblock wszystko %}

Teraz przejdźmy do wyświetlenia naszej listy zakupów i całkowitej kwoty do zapłaty.
Plik views.py modyfikujemy w ukazany sposób.

W funkcji koszyk chcemy, żeby pobrane zostały wszystkie produkty z wyjątkiem tych, gdzie wartość atrybutu dodane jest równa 0, zapisane pod zmienną produkty_koszyk. (Wszystkie produkty, które dodaliśmy do koszyka, przesyłając ich konkretną liczbę sztuk)
Zsumujmy też całą kwotę przez dodanie do ceny startowej 0, kwotę równą ilości dodanych produktów (int - wartości całkowite, integer) razy cenę jednostkową (float - wartości z ułamkiem) i nadpiszmy ją pod zmienną cena (Python automatycznie w tym przypadku wybierze dla niej typ float). W utworzonej pętli for dla każdego zamówionego produktu sumowana jest kwota za wszystkie zamówione sztuki i dodawana do ceny końcowej.
Natomiast w pliku koszyk.html po prostu to wyświetlamy.
Twój koszyk:
{% if produkty_koszyk %} {% for produkt in produkty_koszyk %}nazwa: {{produkt.nazwa}}, ilość zakupionych sztuk: {{produkt.dodane}}
{% endfor %} {% else %}Twój koszyk jest pusty jak słoik po ogórkach
{% endif %}Całkowita kwota do zapłaty: {{cena}} Złotych
{% endblock wszystko %}

Kod sprawdza, czy lista istnieje, czy istnieje jakiś produkt, który ma atrybut dodane inną niż zero. Konkretnie, czy przekazana zmienna produkty_koszyk coś zawiera. Jeśli tak, dla każdego elementu z listy (produktu) wyświetli jego nazwę (produkt.nazwa) oraz ilość zamówionych sztuk (produkt.dodane). Natomiast jeśli zmienna produkty_koszyk jest pusta (nic nie zostało dodane do koszyka), wyświetli napis. Prócz tego wyświetli również całkowitą kwotę do zapłaty za wszystkie produkty w koszyku (obliczoną i przesłaną zmienną cena), jeśli ich nie ma, wyświetli zero.

PS: poprawiliśmy dużą literę w nagłówku dla Koszyk w pliku szablon.html oraz literówkę dla Przekaźnika 4 kanałowego xP w bazie danych.
Podsumowując, udało się wprowadzić nową funkcjonalność “koszyka zakupów”, bez zaburzania struktury już napisanej aplikacji. Mało tego, możemy w łatwy sposób dodać nowe produkty w bazie danych, które będą zachowywały się w dokładnie taki sam sposób co już dodane i automatycznie odziedziczą te same funkcje. W kolejnym rozdziale, spróbujemy zasymulować kupno i wysłanie maila z daną listą oraz zmniejszenie dostępnej ilości o ilość zakupionych sztuk, jak się pewnie domyśliłeś, wprowadzimy nowy atrybut “ilość dostępnych sztuk” dla klasy Produkt.
Category: Kurs Django Podstawa