Ako prvé si spravíme adresár, v ktorom budeme pracoovať
~ mkdir school && cd school
Ako prvé si spravíme adresár, v ktorom budeme pracoovať
~ mkdir school && cd school
Spravíme update a upgrade systému
Arch based
~
sudo pacman -Syyuu
Ubuntu based
~
sudo apt-get -y update && sudoapt-get upgrade
Nainštalujeme virtuálne prostredie
~ pip install virtualenv
Vytvorime prostredie
~ virtualenv .
Alebo ak ho chceme uložiť do nejakého adresára
~ virtualenv venv
Teraz aktivujeme toto prostredie
~ source bin/activate
Ako praktickú ukážku môžeme spustiť tento príkaz pred a po zaktivovaní prostredia
~ pip freeze
Následne si vytvoríme adresár src, v ktorom budeme pracovať
~ mkdir src && cd src
Teraz môžeme nainštalovať Django
~ pip install django
Vytovoríme si vlastný projekt
~
django-admin startproject school_project
&& cd school_project
~
cd ..
Teraz môžeme overiť či aplikácia beží
Najprv musíme spustiť migráciu databázy
~ python manage.py migrate
Teraz spustíme server
Host pre Django je defaultne http://127.0.0.1:8000/
Takže po spustení príkazu môžeme otvoriť prehliadač a
prisť na adresu
~ python manage.py runserver
Vytvoríme si vlastnú aplikáciu
~ python manage.py startapp accounts && cd accounts
Otvoríme si súbor school_project/settings.py pomocou textového editora
~ vi school_project/settings.py
V ňom pridáme do INSTALLED_APPS našu aplikáciu
INSTALLED_APPS = [ 'django.contrib.admin', 'django.contrib.auth', 'django.contrib.contenttypes', 'django.contrib.sessions', 'django.contrib.messages', 'django.contrib.staticfiles', 'accounts' ]
Naimportujeme kni6nicu os a zadefinujeme cestu projektu
import os BASE_DIR = Path(__file__).resolve().parent.parent
Pridáme statickú cestu
STATIC_URL = '/static/' STATICFILES_DIRS = [ os.path.join(BASE_DIR, 'static') ]
Teraz otvoríme súbor urls.py v rovnakom adresáry
~ vi urls.py
V ňom pridáme do urlpatterns odkaz na našu aplikáciu
urlpatterns = [ path('admin/', admin.site.urls), path('accounts/', include('accounts.urls')) ]
A naimportujeme include
from django.contrib import admin
from django.urls import path, include
Teraz vôjdeme do našej aplikácie
~ cd ../accounts/
V ňom vytvoríme súbor urls.py
~ mkdir urls.py
Do neho vložíme
from django.urls import path from . import views urlpatterns = [ path('', views.Login, name='login'), path('logout/', views.Logout, name='logout'), path('register/', views.Register, name='register'), path('ucet/', views.Ucet, name='ucet'), ]
Teraz upravíme súbor views.py
~ vi views.py
Do neho vložíme
from django.shortcuts import render, redirect from django.contrib.auth import authenticate, login, logout from django.contrib import messages from django.contrib.auth.forms import UserCreationForm def Login(request): if request.method=='POST': username=request.POST.get('username') password=request.POST.get('password') user = authenticate(request, username=username, password=password) if user is not None: login(request, user) return redirect('ucet') else: messages.info(request, 'Zlé meno alebo heslo') return render(request, 'accounts/index.html', {}) else: form = UserCreationForm() return render(request, 'accounts/index.html', {}) def Register(request): if request.method=='POST': form = UserCreationForm(request.POST) if form.is_valid(): form.save() return redirect('login') else: form = UserCreationForm() return render(request, 'accounts/register.html', {'form':form}) def Logout(request): logout(request) return render(request, 'accounts/logout.html', {})
Teraz vytvoríme adresár templates a v ňom accounts
~ mkdir templates/accounts
V tom adresáry vytvoríme a upravíme súbor index.html
~ vi templates/accounts/index.html
Do neho vložíme
<!DOCTYPE html> <html lang="sk"> {% load static %} <head> <meta charset="UTF-8"> <meta http-equiv="X-UA-Compatible" content="IE=edge"> <meta name="viewport" content="width=device-width, initial-scale=1.0"> <link rel="stylesheet" href="{% static 'css/accounts/style.css' %}"> <title>Prihlás sa</title> </head> <body> <div class="login_form"> <section class="login-wrapper"> <form id="login" method="post" action="#"> {% csrf_token %} <label for="username">Zadaj Username</label> <input required name="username" type="text" autocapitalize="off" autocorrect="off"/> <label for="heslo">Zadaj Heslo</label> <input class="password" required name="password" type="password" /> <div style="color:white; padding-top: 55px; "> {% for message in messages %} {{message}} {% endfor %} </div> <button type="submit">Prihlás sa</button> <div style="color: white;"> <p>Ešte nemáš učet?</p> <a href="{% url 'register' %}">Registruj sa</a> </div> </form> </section> </div> </body> </html>
V tom adresáry vytvoríme a upravíme súbor register.html
~ vi templates/accounts/register.html
Do neho vložíme
<!DOCTYPE html> <html lang="sk"> {% load static %} <head> <meta charset="UTF-8"> <meta http-equiv="X-UA-Compatible" content="IE=edge"> <meta name="viewport" content="width=device-width, initial-scale=1.0"> <link rel="stylesheet" href="{% static 'css/accounts/style.css' %}"> <title>Zaregistruj sa</title> </head> <body> <div class="login_form"> <section class="login-wrapper"> <form id="login" method="post" action="#"> {% csrf_token %} <label for="username">Zadaj Username</label> <input required name="username" type="text" autocapitalize="off" autocorrect="off"/> <label for="password1">Zadaj Heslo</label> <input class="password" required name="password1" type="password" /> <label for="password2">Zadaj Heslo Znova</label> <input class="password" required name="password2" type="password" /> <div style="color:white; padding-top: 55px; "> {{form.errors}} </div> <button type="submit">Zaregistruj sa</button> <div style="color: white;" style="margin-top: 0;"> <p style="margin-top: 0;">Už u nás máš učet?</p> <a href="{% url 'login' %}" style="margin-top: 0;">Prihlás sa</a> </div> </form> </section> </div> </body> </html>
V tom adresáry vytvoríme a upravíme súbor logout.html
~ vi templates/accounts/logout.html
Do neho vložíme
<!DOCTYPE html> <html lang="sk"> {% load static %} <head> <meta charset="UTF-8"> <meta http-equiv="X-UA-Compatible" content="IE=edge"> <meta name="viewport" content="width=device-width, initial-scale=1.0"> <link rel="stylesheet" href="{% static 'css/accounts/style.css' %}"> <title>Zaregistruj sa</title> </head> <body> <h1>Odhlásený</h1> <a href="{% url 'login' %}">Znova sa Prihlás</a> </body> </html>
V tom adresáry vytvoríme a upravíme súbor ucet.html
~ vi templates/accounts/logout.html
Do neho vložíme
<!DOCTYPE html> <html lang="sk"> {% load static %} <head> <meta charset="UTF-8"> <meta http-equiv="X-UA-Compatible" content="IE=edge"> <meta name="viewport" content="width=device-width, initial-scale=1.0"> <link rel="stylesheet" href="{% static 'css/accounts/style.css' %}"> <title>Vitaj</title> </head> <body> <h1>prihlásený užívateľ {{username}}<h1> <a href="{% url 'logout' %}">Odhlás sa</a> </body> </html>
Ako posledný krok vytvoríme statický adresár do ktorého vložime CSS súbor
//Sme v hlavnom adresáry
~
mkdir static/css/accounts
~
vi static/css/accounts/style.css
Do neho vložíme
*, *:before, *:after { -moz-box-sizing: border-box; -webkit-box-sizing: border-box; box-sizing: border-box; } body, html, .login_form { height: 100%; } body { background: rgb(33,9,110); background: radial-gradient(circle, rgba(33,9,110,1) 0%, rgba(0,2,56,1) 100%); } .login_form { display: -webkit-box; display: -moz-box; display: -ms-flexbox; display: -webkit-flex; display: flex; -webkit-box-flex: center; -moz-box-flex: center; -webkit-flex: center; -ms-flex: center; flex: center; -webkit-justify-content: center; -moz-justify-content: center; justify-content: center; -webkit-box-pack: center; -moz-box-pack: center; -ms-flex-pack: center; -webkit-align-items: center; align-items: center; } .login-wrapper { max-width: 500px; width: 100%; } form { padding: 2em 1em; font-family: helvetica, sans-serif; -webkit-border-radius: 5px; -moz-border-radius: 5px; border-radius: 5px; } form label { color: #fff; margin: 0 3% 0.25em; display: block; font-family: helvetica, sans-serif; } form input { width: 94%; padding: 0.5em 0.25em; margin: 0 3% 1em; font-size: 1.2em; border: 2px solid #000; outline: none; -webkit-transition: all 0.25s; -moz-transition: all 0.25s; -ms-transition: all 0.25s; -o-transition: all 0.25s; transition: all 0.25s; -webkit-border-radius: 5px; -moz-border-radius: 5px; border-radius: 5px; } form input.password { padding-right: 4rem; } form input:focus { border: 2px solid #1fd100; } form button { width: 94%; margin: 2em 3% 0; border: none; background: #228b22; padding: 1em 0; font-size: 1.25em; clear: both; color: white; -webkit-border-radius: 5px; -moz-border-radius: 5px; border-radius: 5px; outline: none; -webkit-transition: all 0.25s; -moz-transition: all 0.25s; -ms-transition: all 0.25s; -o-transition: all 0.25s; transition: all 0.25s; cursor: pointer; } form p { padding-top: 15px; text-align: center; } form a { display: block; text-decoration: none; text-align: center; width: 94%; margin: 2em 3% 0; border: none; background: #228b22; padding: 1em 0; font-size: 1.25em; clear: both; color: white; -webkit-border-radius: 5px; -moz-border-radius: 5px; border-radius: 5px; outline: none; -webkit-transition: all 0.25s; -moz-transition: all 0.25s; -ms-transition: all 0.25s; -o-transition: all 0.25s; transition: all 0.25s; cursor: pointer; }
Na začiatok mierna rekapitulácia
Čo je django?
Django sa stará o backend pre web aplikácie
Stará sa o autentifikáciu užívateľov, administráciu obsahu,
komunikáciu medzi stránkami a mnoho iného
Najprv si spustíme virtuálne prostredie
Následne spustíme Django
Ako prvé môžeme začať s vlastnou autentifikáciou usera a pozrieť sa bližšie na to, ako sa o to django stará a ako "prebrať" django túto moc
Ako prvé vôjdeme do súboru models.py
//Sme v hlavnom adresáry
~
vim accounts/models.py
Do neho vložíme
from django.db import models from django.contrib.auth.models import AbstractBaseUser, BaseUserManager class MyAccountManager(BaseUserManager): def create_user(self, email, krstne, priezvisko, password=None): if not email: raise ValueError('Užívateľ musí mať validný email') if not krstne: raise ValueError('Užívateľ musí mať validné krstne meno') if not priezvisko: raise ValueError('Užívateľ musí mať validné priezvisko') user = self.model( email=self.normalize_email(email), krstne=krstne, priezvisko=priezvisko, password=password, ) user.set_password(password) user.save(using=self._db) return user def create_superuser(self, email, krstne, priezvisko, password=None): user = self.create_user( email=self.normalize_email(email), krstne=krstne, priezvisko=priezvisko, password = password, ) user.set_password(password) user.is_admin = True user.is_superuser = True user.is_staff = True user.save(using=self._db) return user def update_user(self, krstne, priezvisko, pk): user = Account.objects.get(pk=pk) user.krstne = krstne user.priezvisko = priezvisko user.save() class Account(AbstractBaseUser): email = models.EmailField(verbose_name='email', max_length=60, unique=True) krstne = models.CharField(max_length=120) priezvisko = models.CharField(max_length=120) date_joined = models.DateTimeField(verbose_name='date joined', auto_now_add=True) last_login = models.DateTimeField(verbose_name='last login', auto_now=True) is_admin = models.BooleanField(default=False) is_staff = models.BooleanField(default=False) is_active = models.BooleanField(default=True) is_superuser = models.BooleanField(default=False) objects = MyAccountManager() USERNAME_FIELD='email' REQUIRED_FIELDS=['krstne', 'priezvisko'] def __str__(self): return self.email def has_perm(self, perm, obj=None): return self.is_admin def has_module_perms(self, app_label): return True
Tu máme možnosť využiť triedu AbstractBaseUser a AbstractUser
Rozdiel medzi nimi je, že AbstractUser može zdediť polia z hlavnej metódy
Naopak AbstractBaseUser je nútený vytvoriť všetko nanovo teda
zadefinovať vlastné polia.
Teraz nám treba upraviť settings.py aby Django vedel že budeme využívať vlasntú autentifikáciu
//Sme v hlavnom adresáry
~
vim school_project/settings.py
Do neho vložíme
AUTH_USER_MODEL='accounts.Account'
Teraz vytvoríme vlastý formulár aby sme mohli používať model ktorý sme
pred chvíľou vytvorili
Najprv vytvoríme súbor forms.py v adresáry accounts
//Sme v hlavnom adresáry
~
vim accounts/forms.py
Následne ho upravíme
from django.forms import ModelForm from django import forms from .models import Account from django.utils.translation import ugettext, ugettext_lazy as _ class signup_form(forms.ModelForm): error_messages = { 'duplicate_username': _("S týmto emailom už je prihlásený iný užívateľ."), 'password_mismatch': _("Heslá sa nezhodujú."), } heslo1 = forms.CharField(label=_("Password"), widget=forms.PasswordInput) heslo2 = forms.CharField(label=_("Password confirmation"), widget=forms.PasswordInput, help_text=_("Zadaj rovnaké heslo ako si zadal vyššie.")) class Meta: model = Account fields = ("email",'krstne','priezvisko') def clean_username(self): username = self.cleaned_data["uzivatelske_meno"] try: User._default_manager.get(username=username) except User.DoesNotExist: return username raise forms.ValidationError(self.error_messages['duplicate_username']) def clean_heslo2(self): heslo1 = self.cleaned_data.get("heslo1") heslo2 = self.cleaned_data.get("heslo2") if heslo1 and heslo2 and heslo1 != heslo2: raise forms.ValidationError( self.error_messages['password_mismatch']) return heslo2 def save(self, commit=True): user = super(signup_form, self).save(commit=False) user.set_password(self.cleaned_data["heslo1"]) if commit: user.save() return user
Teraz nám bude treba migrovať túto aplikáciu, pretože sme pridali nový model (tabuľku v databáze), a upravili sme si tabuľku User
//Sme v hlavnom adresáry
~
python manage.py makemigrations
~
python manage.py migrate
Teraz si môžeme vytvoriť nové backandové služby pre kontrolu prihlásenia užívateľa
//Sme v hlavnom adresáry
~
vim accounts/backends.py
Následne ho upravíme
from django.contrib.auth import get_user_model from django.contrib.auth.backends import ModelBackend class CaseInsensitiveModelbackend(ModelBackend): def authenticate(self, request, email=None, heslo=None, **kwargs): UserModel = get_user_model() if email is None: email = kwargs.get(UserModel.USERNAME_FIELD) try: case_insensitive_username_field = '{}__iexact'.format(UserModel.USERNAME_FIELD) user = UserModel._default_manager.get(**{case_insensitive_username_field: email}) except UserModel.DoesNotExist: UserModel().set_password(heslo) else: if user.check_password(heslo) and self.user_can_authenticate(user): return user
Avšak Django nevie o tom, že mi chceme kontrolovať podľa nejakých vlastných backend pravidiel a ako som už v minulosti avizoval všetko tohoto rázu sa rieši v settings.py
//Sme v hlavnom adresáry
~
vim school_project/settings.py
Do neho vložíme
AUTHENTICATION_BACKENDS = { 'django.contrib.auth.backends.AllowAllUsersModelBackend', 'accounts.backends.CaseInsensitiveModelbackend', }
Teraz si vytvoríme superužívateľa (admina)
//Sme v hlavnom adresáry
~
python manage.py createsuperuser
Následne vypíšeme všetky požadované údaje
Teraz sme v stave kedy aj keď máme vytvorený vlastný model aj vlastný formulár avšak nemáme html korešpondujúce s týmto registračným a prihlasovacím formulárom
//Sme v hlavnom adresáry
~
vim accounts/template/accounts/register.html
Následne ho upravíme
<!DOCTYPE html> <html lang="sk"> {% load static %} <head> <meta charset="UTF-8"> <meta http-equiv="X-UA-Compatible" content="IE=edge"> <meta name="viewport" content="width=device-width, initial-scale=1.0"> <link rel="stylesheet" href="{% static 'css/accounts/style.css' %}"> <title>Zaregistruj sa</title> </head> <body> <div class="login_form"> <section class="login-wrapper"> <form id="login" method="post" action="#"> {% csrf_token %} <label for="email">Zadaj Email</label> <input required name="email" type="text" autocapitalize="off" autocorrect="off"/> <label for="krstne">Zadaj Meno</label> <input required name="krstne" type="text" autocapitalize="off" autocorrect="off"/> <label for="priezvisko">Zadaj Priezvisko</label> <input required name="priezvisko" type="text" autocapitalize="off" autocorrect="off"/> <label for="heslo1">Zadaj Heslo</label> <input class="password" required name="heslo1" type="password" /> <label for="heslo2">Zadaj Heslo Znova</label> <input class="password" required name="heslo2" type="password" /> <div style="color:white; padding-top: 55px; "> {{form.errors}} </div> <button type="submit">Zaregistruj sa</button> <div style="color: white;" style="margin-top: 0;"> <p style="margin-top: 0;">Už u nás máš učet?</p> <a href="{% url 'login' %}" style="margin-top: 0;">Prihlás sa</a> </div> </div> </form> </section> </div> </body> </html>
Teraz upravíme aj login užívateľa
//Sme v hlavnom adresáry
~
vim accounts/template/accounts/index.html
Následne ho upravíme
<!DOCTYPE html> <html lang="sk"> {% load static %} <head> <meta charset="UTF-8"> <meta http-equiv="X-UA-Compatible" content="IE=edge"> <meta name="viewport" content="width=device-width, initial-scale=1.0"> <link rel="stylesheet" href="{% static 'css/accounts/style.css' %}"> <title>Prihlás sa</title> </head> <body> <div class="login_form"> <section class="login-wrapper"> <form id="login" method="post" action="#"> {% csrf_token %} <label for="email">Zadaj Email</label> <input required name="email" type="text" autocapitalize="off" autocorrect="off"/> <label for="heslo">Zadaj Heslo</label> <input class="password" required name="heslo" type="password" /> <div style="color:white; padding-top: 55px; "> {% for message in messages %} {{message}} {% endfor %} </div> <button type="submit">Prihlás sa</button> <div style="color: white;"> <p>Ešte nemáš učet?</p> <a href="{% url 'register' %}">Registruj sa</a> </div> <div class="icons-mlm" style="text-align: center; padding-top: 25px"> </form> </section> </div> </body> </html>
Posledný krok ktorý nám ostáva je upraviť views.py aby využívala formulu (tabuľku), ktorú sme vytvorili
//Sme v hlavnom adresáry
~
vim accounts/viewvs.py
Upravíme ho do nasledovného tvaru
from django.shortcuts import render, redirect from .forms import signup_form from django.contrib.auth import authenticate, login, logout from django.contrib import messages from .models import Account def Login(request): if request.method=='POST': email = request.POST.get('email') password = request.POST.get('heslo') user = authenticate(request, username=email, password=password) if user is not None: login(request, user) return redirect('ucet') else: messages.info(request, 'Zlé meno alebo heslo') return render(request, 'accounts/index.html', {}) else: form = signup_form() return render(request, 'accounts/index.html', {}) def Register(request): if request.method=='POST': form = signup_form(request.POST) if form.is_valid(): form.save() messages.success(request, 'Bol vytvorený užívateľ ' + request.POST.get('email')) return redirect('login') else: form = signup_form() return render(request, 'accounts/register.html', {'form':form}) def Logout(request): logout(request) return render(request, 'accounts/logout.html', {}) # @login_required def Ucet(request): if request.user.is_authenticated: user = request.user context = {'username': user.email, 'password': user.password} return render(request, 'accounts/ucet.html', context ) else: return redirect('../accounts/login')
Na začiatku som spomenul že Django sa stará o autentifikáciu a teraz sme si
ukázali malú časť toho, v čom nám Django uľahčil robotu čo sa autentifikácie
týka
Ako ďalšia vec ktorú som spomenul, o ktorú sa Django stará bola administrácia
obsahu
Ak si pamätáte na minulej prednáške som ukazoval čo vidíme ak sa prihlásime
cez adresu 127.0.0.1:8000/admin/
Pre tých ktorý nepamätajú tak sme tam videli všetky modely, ktoré sme mali
defaultne vytvorené bol tam odsek pre users a bol tam odsek pre Groups
Avšak teraz keďže sme si vytvorili vlastnú tabuľku musíme djangu povedať ako
chceme aby zobrazoval tento obsah
Toto spravíme v aplikácií v súbore admin.py
Poďme sa teda vrhnúť na to a upraviť tento súbor
//Sme v hlavnom adresáry
~
vim accounts/admin.py
Následne ho upravíme
from django.contrib import admin from django.contrib.auth.admin import UserAdmin from .models import Account class AccountAdmin(UserAdmin): list_display =('email', 'krstne', 'priezvisko', 'date_joined', 'last_login', 'is_admin', 'is_staff') search_fields =('email', 'krstne', 'priezvisko') readonly_fields =('id', 'date_joined', 'last_login') filter_horizontal =() list_filter =() fieldsets =() add_fieldsets =('email',) ordering =('email',) admin.site.register(Account, AccountAdmin)
Teraz sme si prešli nejakú funkcionalitu django
Vašou úlohou teraz bude vytvoriť obsah potom čo sa užívateľ prihlási
Čo teda bude vašou úlohou?
Vytvoriť blog, kde užívatelia budú môcť postovať nejaké príspevky
Neviete ako na to?
Odrazte sa od týchto bodov:
1. Vytvorte novú aplikáciu s názvom blog
2. Vytvorte v nej model ktorý bude obsahovať všetky podstatné polia (autor, obsah ...)
3. vytvorte formulár ktorý budú používatelia používať pri vytváraní nových postov
4. vytvorte view pre zobrazenie a vytvorenie resp úpravu daného postu
5. zobrazte všetky posty na obrazovke
Najprv nainstalujeme Docker ak ešte nemáme
Arch based
~
sudo pacman -S docker
Ubuntu based
~
sudo apt-get install docker
Teraz vytvoríme súbor s názvom Dockerfile
Tento súbor vytvárame bez prípony
Tento súbor musí buyťvytvorený v hlavnej adresárovej
štruktúry
Vojdeme teda späť do adresára school_project
~ vi Dockerfile
Do neho vložíme
FROM python:3 ENV PYTHONUNBUFFERED 1 RUN mkdir /app WORKDIR /app COPY requirements.txt /app/ RUN pip install -r requirements.txt COPY . /app/
Teraz vytvoríme docker-compose.yml
~ vi docker-compose.yml
Do neho vložíme
version: '3' services: web: build: . command: python src/school_project/manage.py runserver 0.0.0.0:8000 volumes: - .:/app ports: - "8000:8000"
Ako poseldný krok nám bude treba povedať Djangu aby
počúval na adrese 0.0.0.0
To spravíme úpravou súboru settings.py
~ vi src/school_project/settings.py
V ňom upravíme ALLOWED_HOST=[]
ALLOWED_HOSTS = ['0.0.0.0']