Kurs Django Podstawa – #6 – Konta dla nowych użytkowników – własny koszyk

Posted on: August 7, 2024

Kurs Django Podstawa – #6 – Konta dla nowych użytkowników – własny koszyk

Kurs Django Podstawa – #6 – Konta dla nowych użytkowników – własny koszyk

„Django Sklep - Konta dla nowych użytkowników”

 

W tym rozdziale przedstawimy, jak w prosty sposób stworzyć bazę użytkowników oraz system rejestracji i logowania. Dzięki temu każdy użytkownik będzie miał swój własny koszyk. Zatem do dzieła. Zobacz, jakie to łatwe. Ten rozdział będzie nieco dłuższy, ale spokojnie, nawet nie zauważysz, kiedy skończysz tworzyć bazę danych.

Najpierw, aby zachować porządek w naszych plikach i umożliwić implementację bazy użytkowników, stworzymy nową aplikację w projekcie. Gdy masz już aktywny projekt (w ramach przypomnienia) w otwartym terminalu, w katalogu, w którym znajdują się wszystkie pliki:

Projekt1_env\Scripts\activate

Gdy projekt jest aktywny (pojawiły się nawiasy), wpisz:

python manage.py startapp baza

Zobacz, że teraz w strukturze projektu pojawił się folder „baza” z takimi plikami, jak folder „Sklep”.

kurs-django-robot-6-im1.png

Teraz w pliku Settings.py dopisz nazwę nowej aplikacji:

'baza',
kurs-django-robot-6-im2.png

Teraz zaktualizuj plik urls.py:

from baza.views import * from django.urls import path, include

oraz dodaj Django informację, że stworzymy nowe linki dla aplikacji „baza”:

path('baza/', include('baza.urls')),

To bardziej uporządkowany sposób na łączenie linków z funkcjami w Django. Przy większej ilości aplikacji w jednym projekcie zalecamy właśnie takie podejście.

kurs-django-robot-6-im3.png

Czyli w pliku głównym dajemy znać Django: „Hej, tworzymy nowe ścieżki, które zaczynają się od „baza” i będą znajdowały się w pliku „urls” w folderze „baza”.

Skorzystamy z wbudowanej funkcji na bazę danych, którą oferuje Django. Aby to zrobić, w naszym szablonie zdefiniuj nowe linki do rejestracji, logowania i wylogowania.

Dodajmy również, aby wyświetlała się nazwa użytkownika, jeśli jest zalogowany. Zmodyfikuj plik szablon.html w następujący sposób:

<!DOCTYPE html> <html lang="pl"> <head> <meta charset="UTF-8"> <title>Sklep</title> </head> <body> <h1>Witaj w naszym sklepie</h1><br> <p> <a href="/">Strona Główna</a> &nbsp;&nbsp;&nbsp;&nbsp; <a href="/produkty">Pokaż mi swoje towary</a> &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; <a href="/koszyk">Koszyk</a> &nbsp;&nbsp;&nbsp; {% if user.is_authenticated %} Witaj, {{user.username}}. <a href="{% url 'baza:logout' %}">Wyloguj</a> {% else %} <a href="{% url 'baza:register' %}">Rejestracja</a>&nbsp;&nbsp;&nbsp; <a href="{% url 'baza:login' %}">Zaloguj</a> {% endif %} </p> {% block wszystko %}{% endblock wszystko %} </body> </html>

Dodaliśmy trzy, póki co puste, linki, kryjące się pod np. napisem „Wyloguj”, z akceptowalną formą kodu.

kurs-django-robot-6-im4.png

Teraz w aplikacji „baza” stwórz plik urls.py, a następnie przepisz poniższy kod:

from django.urls import path, include from . import views app_name = 'baza' urlpatterns = [ path('', include('django.contrib.auth.urls')), path('register/', views.register, name ='register'), ]

Funkcje „login” i „logout” są już zdefiniowane w podstawowych funkcjach Django, dlatego nie musimy ich tutaj zapisywać, ale musimy zachować odpowiednią formę, żeby z nich skorzystać.

kurs-django-robot-6-im5.png

Jak zauważyłeś na zdjęciu powyżej, pojawiły się również trzy nowe pliki HTML: login, register oraz logged_out, które znajdują się w strukturze baza->templates->registration i wyglądają następująco:

{% extends 'Sklep/szablon.html' %} {% block wszystko %} {% if form.errors %}

Spróbuj ponownie, coś pomieszałeś.

{% endif %}
{% csrf_token %} {{form.as_p}}
{% endblock wszystko %}
kurs-django-robot-6-im6.png
{% extends 'Sklep/szablon.html' %} {% block wszystko %}

Wylogowałeś się, wszystko git.

{% endblock wszystko %}
kurs-django-robot-6-im7.png
{% extends 'Sklep/szablon.html' %} {% block wszystko %}
{% csrf_token %} {{form.as_p}}
{% endblock wszystko %}
kurs-django-robot-6-im8.png

Wszystkie trzy pliki dziedziczą strukturę po szablonie, ale aby można było wykorzystać gotową bazę danych z Django, trzeba było dostosować kod do standardów przedstawionych powyżej.

W pliku views.py w aplikacji „baza” dodaj jedną funkcję:

from django.shortcuts import render, redirect from django.contrib.auth import login from django.contrib.auth.forms import UserCreationForm def register(request): if request.method != 'POST': form = UserCreationForm() else: form = UserCreationForm(data=request.POST) if form.is_valid(): new_user = form.save() login(request, new_user) return redirect('/') context = {'form': form} return render(request, 'registration/register.html', context)
kurs-django-robot-6-im9.png

Sprawdź, czy wszystko działa, spróbuj się zalogować na konto utworzone na samym początku administratora, potem dodaj kilka kont na testy (po prostu zarejestruj kilka nowych kont). Powinno to wyglądać mniej więcej tak:

kurs-django-robot-6-im10.png
kurs-django-robot-6-im11.png
kurs-django-robot-6-im12.png

Gotowa rejestracja prezentuje się jak poniżej. Na tym etapie taka wystarczy:

kurs-django-robot-6-im13.png

Oraz widok bazy danych z poziomu administratora, pokazujący całą listę wszystkich zarejestrowanych użytkowników z kodowanymi hasłami:

kurs-django-robot-6-im14.png

PS: Klasa „Koszyk” będzie omówiona w dalszej kolejności.

Wchodząc głębiej, możesz zobaczyć, że jest kilka dodatkowych funkcji, z których można skorzystać. Jednak na razie pozostaniemy przy standardowej wersji.

Teraz, gdy mamy już kilka utworzonych kont, zmodyfikujemy naszą aplikację tak, aby koszyk był prywatny dla każdego konta i wysyłał spersonalizowane zamówienie. DO IT!

Można to zrealizować na wiele sposobów. My dodamy nową klasę, która będzie powiązana z utworzoną wcześniej bazą danych poprzez atrybut „nazwa użytkownika” oraz powiązana z wszystkimi produktami. W ten sposób, po dodaniu konkretnego produktu do koszyka, zostanie utworzona kopia obiektu klasy Produkt (z atrybutami: nazwa, cena, dodane) np. „Kamerki”, ale dodatkowo z nazwą danego użytkownika. Docelowo w bazie danych Django będzie to wyglądało mniej więcej tak:

kurs-django-robot-6-im15.png

Aplikacji „baza” już nie będziemy modyfikować, będziemy z niej tylko korzystać. Wracamy do aplikacji „Sklep”.

Najpierw stworzymy nową klasę „Koszyk”, która będzie miała te same atrybuty co klasa „Produkt”, ale dodatkowo będzie zależna od zalogowanego użytkownika. Dodaj import „User” oraz nową klasę w pliku models.py w aplikacji „Sklep”:

from django.contrib.auth.models import User class Koszyk(models.Model): user = models.ForeignKey(User, on_delete=models.CASCADE) nazwa_user = models.CharField(max_length=50) opis_user = models.TextField(blank=True) cena_user = models.TextField(blank=True) dodane_user = models.IntegerField(default=0) def str(self): name = str(self.nazwa_user) + " - " + str(self.user) return name class Meta: verbose_name = "Koszyk" verbose_name_plural = "Koszyk"
kurs-django-robot-6-im16.png

W pliku admin.py dodaj klasę „Koszyk”:

from django.contrib import admin # Register your models here. from .models import Produkt, Koszyk admin.site.register(Produkt) admin.site.register(Koszyk)
kurs-django-robot-6-im17.png

W pliku settings.py dopisz frazę na samym dole:

LOGIN_URL = 'baza:login'
kurs-django-robot-6-im18.png

Wykonaj standardową procedurę po modyfikacji pliku models.py – w konsoli wpisz dwie komendy po sobie:

python manage.py makemigrations python manage.py migrate

Teraz zajmiemy się modyfikacją pliku views.py w aplikacji „Sklep”. Chcemy, aby wszystkie funkcje powiązane z koszykiem oddziaływały na obiekty z klasy „Koszyk”, a nie klasy „Produkt”. Po pierwsze, dodaj odpowiednie biblioteki:

from django.shortcuts import render, redirect from django.contrib.auth.decorators import login_required # Create your views here. from Sklep.models import Produkt, Koszyk from .forms import KoszykForm
kurs-django-robot-6-im19.png

Fraza @login_required oznacza, że funkcja wykona się dopiero, gdy użytkownik jest zalogowany. W przeciwnym razie nastąpi przekierowanie do strony logowania.

Dodaj funkcję „dodajkoszyk”:

@login_required def dodajkoszyk(request, id): produkt = Produkt.objects.get(pk=id) p_id = id if Koszyk.objects.filter(user=request.user, nazwa_user=produkt.nazwa).exists(): produkt_koszyk = Koszyk.objects.get(user=request.user, nazwa_user=produkt.nazwa) else: Koszyk.objects.create(user=request.user, nazwa_user=produkt.nazwa, cena_user=produkt.cena, dodane_user=produkt.dodane) produkt_koszyk = Koszyk.objects.get(user=request.user, nazwa_user=produkt.nazwa) if request.method != 'POST': form = KoszykForm(instance=produkt_koszyk) else: form = KoszykForm(instance=produkt_koszyk, data=request.POST) if form.is_valid(): form.save() dane = {'produkt': produkt, 'p_id': p_id, 'form': form} return render(request, 'Sklep/produkt.html', dane)
kurs-django-robot-6-im20.png

Wprowadziliśmy warunek na aktualizację ilości danego produktu, jeśli ten obiekt został już utworzony, lub jego utworzenie dziedzicząc atrybuty po danym produkcie i jednocześnie zalogowanym użytkowniku. Teraz należy zaktualizować formularz, aby odnosił się do klasy „Koszyk”:

from django import forms from .models import Produkt, Koszyk class KoszykForm(forms.ModelForm): class Meta: model = Produkt fields = ['dodane'] labels = {'dodane': ''} class KoszykForm(forms.ModelForm): class Meta: model = Koszyk fields = ['dodane_user'] labels = {'dodane_user': ''}
kurs-django-robot-6-im21.png

Pliku „produkt.html” nie musimy modyfikować. Jego wygląd będzie bazował na klasie „Produkty”, natomiast pod powłoką komputer będzie czarował i dodawał obiekty typu „Koszyk”. Wracamy do pliku i modyfikujemy następną funkcję „koszyk”:

@login_required def koszyk(request): produkty_koszyk = Koszyk.objects.filter(user=request.user) cena = 0 for produkt in produkty_koszyk: cena = cena + float(produkt.cena_user) * int(produkt.dodane_user) cena = float(round(cena, 2)) dane = {'produkty_koszyk': produkty_koszyk, 'cena': cena} return render(request, 'Sklep/koszyk.html', dane)
kurs-django-robot-6-im22.png

Ta funkcja wyśle do pliku „koszyk.html” produkty w koszyku konkretnego zalogowanego użytkownika. Zaktualizujemy teraz plik „koszyk.html”:

<!DOCTYPE html> <html lang="pl"> <head> <meta charset="UTF-8"> <title>Sklep</title> </head> <body> <h1>Twój koszyk:</h1> <p> <a href="/">Strona Główna</a> &nbsp;&nbsp;&nbsp;&nbsp; <a href="/produkty">Pokaż mi swoje towary</a> &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; <a href="/koszyk">Koszyk</a> &nbsp;&nbsp;&nbsp; {% if user.is_authenticated %} Witaj, {{user.username}}. <a href="{% url 'baza:logout' %}">Wyloguj</a> {% else %} <a href="{% url 'baza:register' %}">Rejestracja</a>&nbsp;&nbsp;&nbsp; <a href="{% url 'baza:login' %}">Zaloguj</a> {% endif %} </p> {% block wszystko %} <p>Twój koszyk:</p> {% if produkty_koszyk %} {% for produkt in produkty_koszyk %} <p>nazwa: {{produkt.nazwa_user}}, ilość zakupionych sztuk: {{produkt.dodane_user}} &nbsp; <a href="/kosz/1/{{produkt.id}}">+</a>&nbsp; <a href="/kosz/0/{{produkt.id}}">-</a> </p> {% endfor %} {% else %} <p>Twój koszyk jest pusty jak słoik po ogórkach</p> {% endif %} <br> <p>Całkowita kwota do zapłaty: {{cena}} Złotych</p> <a href="/wyslij">Złóż zamówienie</a> {% endblock wszystko %} </body> </html>
kurs-django-robot-6-im23.png
@login_required def kosz(request, id1, id2): produkt_wyb = Koszyk.objects.get(pk=id2) if id1 == '1': produkt_m = int(produkt_wyb.dodane_user) + 1 else: produkt_m = int(produkt_wyb.dodane_user) - 1 Koszyk.objects.filter(pk=id2).update(dodane_user=produkt_m) produkty_koszyk = Koszyk.objects.filter(user=request.user) cena = 0 for produkt in produkty_koszyk: cena = cena + float(produkt.cena_user) * int(produkt.dodane_user) cena = float(round(cena, 2)) dane = {'produkty_koszyk': produkty_koszyk, 'cena': cena} return render(request, 'Sklep/koszyk.html', dane)
kurs-django-robot-6-im24.png

W końcu dodajemy funkcję „wyslij”:

@login_required def wyslij(request): produkty_koszyk = Koszyk.objects.filter(user=request.user) cena = 0 for produkt in produkty_koszyk: cena = cena + float(produkt.cena_user) * int(produkt.dodane_user) cena = float(round(cena, 2)) file = open(f'C:/Users/Marcin/Desktop/zamowienie_{request.user}.txt', "w") file.write(f"rachunek użytkownika: {request.user}\n") for obiekt in produkty_koszyk: file.write(f"nazwa: {obiekt.nazwa_user}, ilość zakupionych sztuk: {obiekt.dodane_user}\n") file.write(f"kwota do zapłaty: {cena}") file.close() Koszyk.objects.filter(user=request.user).delete() produkty_koszyk = False cena = 0 dane = {'produkty_koszyk': produkty_koszyk, 'cena': cena} return render(request, 'Sklep/koszyk.html', dane)
kurs-django-robot-6-im25.png

Koniec! Udało się stworzyć bardzo funkcjonalną stronę z produktami, którą można rozszerzać na wiele sposobów. Teraz zaloguj się na kilka kont i sprawdź, czy wszystko działa. W rezultacie powinna pojawić się inna lista produktów w koszyku dla każdego użytkownika.

Category: Kurs Django Podstawa