This shows you the differences between two versions of the page.
|
ii:lab:laborator5 [2021/01/09 01:01] eduard.staniloiu |
ii:lab:laborator5 [2021/01/20 08:51] (current) florin.stancu [Exerciții] |
||
|---|---|---|---|
| Line 32: | Line 32: | ||
| </code> | </code> | ||
| + | |||
| + | <note important> | ||
| + | Dacă nu vă merge (diferite setup-uri), încercați una dintre comenzile echivalente: | ||
| + | <code bash> | ||
| + | pip3 install ... # pip pentru python3, dacă este aliasat | ||
| + | python3 -mpip install ... # pentru python3 | ||
| + | |||
| + | python -mpip install ... # pentru python2 | ||
| + | </code> | ||
| + | </note> | ||
| ===== Hello World ===== | ===== Hello World ===== | ||
| Line 191: | Line 201: | ||
| După ce am făcut modificările, accesăm pagina [[http://127.0.0.1:5000]]. | După ce am făcut modificările, accesăm pagina [[http://127.0.0.1:5000]]. | ||
| + | |||
| + | |||
| + | ==== Structuri de control ==== | ||
| + | |||
| + | În cadrul template-urilor Jinja putem folosi și structuri de control precum **if** și **for**. | ||
| + | Sintaxa pentru acestea este următoarea: | ||
| + | |||
| + | <code html> | ||
| + | |||
| + | <html> | ||
| + | <head> | ||
| + | {% if title %} | ||
| + | <title>{{ title }}</title> | ||
| + | {% else %} | ||
| + | <title>Welcome</title> | ||
| + | {% endif %} | ||
| + | </head> | ||
| + | <body> | ||
| + | {% for user in users %} | ||
| + | <div><p>{{ user.username }}</p></div> | ||
| + | {% endfor %} | ||
| + | </body> | ||
| + | </html> | ||
| + | |||
| + | </code> | ||
| + | |||
| + | <note tip> | ||
| + | |||
| + | În cadrul **{****{** ... **}****}** folosim cod python. | ||
| + | |||
| + | </note> | ||
| + | |||
| + | ==== Extinderea unor template-uri de bază ==== | ||
| + | |||
| + | Majoritatea paginilor unei aplicații web conțin componente comune (cum ar fi bara de navigație). | ||
| + | Pentru a evita scrierea repetată a componentelor comune în fiecare pagină, putem folosi **template inheritance**: componentele comune sunt scrise într-un template de bază care este apoi extins de fiecare pagină. | ||
| + | |||
| + | Pentru aceasta, în directorul **~/hello-flask/templates** definim fișierul **base.html**, ca mai jos: | ||
| + | |||
| + | <code html base.html> | ||
| + | |||
| + | <html> | ||
| + | <head> | ||
| + | {% if title %} | ||
| + | <title>{{ title }}</title> | ||
| + | {% else %} | ||
| + | <title>Welcome</title> | ||
| + | {% endif %} | ||
| + | </head> | ||
| + | <body> | ||
| + | <div><a href="/index">Home</a></div> | ||
| + | <hr> | ||
| + | {% block content %}{% endblock %} | ||
| + | </body> | ||
| + | </html> | ||
| + | |||
| + | </code> | ||
| + | |||
| + | Fișierul template de mai sus este acum baza noastră. | ||
| + | El definește structura generală a paginii. | ||
| + | Orice pagină nouă o să extindă această bază și apoi trebuie să definească doar blocul **content**. | ||
| + | |||
| + | Astfel, modificăm fișierul **~/hello-flask/templates/index.html** ca mai jos: | ||
| + | |||
| + | <code html index.html> | ||
| + | |||
| + | {% extends "base.html" %} | ||
| + | |||
| + | {% block content %} | ||
| + | <h1>Hello, {{ user.username }}!</h1> | ||
| + | {% endblock %} | ||
| + | |||
| + | </code> | ||
| + | |||
| + | ===== Bootstrap ===== | ||
| + | |||
| + | [[https://getbootstrap.com/docs/5.0/getting-started/introduction/|Bootstrap]] este un framework foarte popular folosit pentru a crea interfețe cu utilizatorul (UI). | ||
| + | |||
| + | Pentru a folosi **Bootstrap**, adăugăm următoarele linii în fișierul **base.html** | ||
| + | |||
| + | <code html base.html> | ||
| + | |||
| + | <html> | ||
| + | <head> | ||
| + | <meta charset="utf-8"> | ||
| + | <meta name="viewport" content="width=device-width, initial-scale=1"> | ||
| + | |||
| + | <link href="https://cdn.jsdelivr.net/npm/bootstrap@5.0.0-beta1/dist/css/bootstrap.min.css" rel="stylesheet" crossorigin="anonymous"> | ||
| + | <link href="https://cdn.jsdelivr.net/npm/bootstrap-icons@1.3.0/font/bootstrap-icons.css" rel="stylesheet"> | ||
| + | |||
| + | <script src="https://cdn.jsdelivr.net/npm/@popperjs/core@2.5.4/dist/umd/popper.min.js" crossorigin="anonymous"></script> | ||
| + | <script src="https://cdn.jsdelivr.net/npm/bootstrap@5.0.0-beta1/dist/js/bootstrap.min.js" crossorigin="anonymous"></script> | ||
| + | |||
| + | {% if title %} | ||
| + | <title>{{ title }}</title> | ||
| + | {% else %} | ||
| + | <title>Welcome</title> | ||
| + | {% endif %} | ||
| + | </head> | ||
| + | <body> | ||
| + | <div><a href="/index">Home</a></div> | ||
| + | <hr> | ||
| + | {% block content %}{% endblock %} | ||
| + | </body> | ||
| + | </html> | ||
| + | |||
| + | </code> | ||
| + | |||
| + | Acum putem folosi Bootstrap pentru a ne înfrumuseța pagina. | ||
| + | Începem prin a centra textul din fișierul **index.html**: | ||
| + | |||
| + | <code html index.html> | ||
| + | |||
| + | {% extends "base.html" %} | ||
| + | |||
| + | {% block content %} | ||
| + | <h1 class="text-center">Hello, {{ user.username }}!</h1> | ||
| + | {% endblock %} | ||
| + | |||
| + | </code> | ||
| + | |||
| + | Observăm că a fost necesar doar să adăugăm clasa **text-center** elementului **h1**. | ||
| + | Acesta este modul de funcționare Bootstrap: tot ce trebuie făcut este să includem elementele în clasa pe care ne-o dorim. | ||
| + | |||
| + | Bootstrap împarte (imaginar) pagina în 12 [[https://getbootstrap.com/docs/5.0/layout/grid/|coloane]]. | ||
| + | Noi apoi decidem, prin intermediul atributului **class**, [[https://getbootstrap.com/docs/5.0/layout/grid/|câte din aceste coloane vor ocupa elementele noastre]]. | ||
| + | |||
| + | De exemplu: | ||
| + | |||
| + | <code html> | ||
| + | |||
| + | <div class="container"> | ||
| + | <div class="row"> | ||
| + | <div class="col-sm"> | ||
| + | One of three columns | ||
| + | </div> | ||
| + | <div class="col-sm"> | ||
| + | One of three columns | ||
| + | </div> | ||
| + | <div class="col-sm"> | ||
| + | One of three columns | ||
| + | </div> | ||
| + | </div> | ||
| + | </div> | ||
| + | |||
| + | </code> | ||
| + | |||
| + | Exemplul de mai sus va împărți lățimea rândului în mod egal între cele trei coloane. | ||
| + | |||
| + | ==== Bootstrap Icons ==== | ||
| + | |||
| + | Bootstrap ne oferă și un set de imagini SVG pe care le putem folosi pe post de [[https://icons.getbootstrap.com/|icons]]. | ||
| + | |||
| + | Ca să înlocuim textul **Home** din fișierul **base.html** cu un icon, trebuie să: | ||
| + | * identificăm icon-ul unei [[https://icons.getbootstrap.com/icons/house/|case]] | ||
| + | * înlocuim textul **Home** cu textul din **Icon font**. | ||
| + | |||
| + | Astfel, textul | ||
| + | |||
| + | <code html> | ||
| + | <div><a href="/index">Home</a></div> | ||
| + | </code> | ||
| + | | ||
| + | Devine | ||
| + | | ||
| + | <code html> | ||
| + | <div><a href="/index"><i class="bi bi-house"></i></a></div> | ||
| + | </code> | ||
| + | |||
| + | |||
| + | ===== Exerciții ===== | ||
| + | |||
| + | O să scrieți o aplicație web care are rolul unui CV. | ||
| + | CV-ul trebuie să conțină secțiunile: Work Experience, Education, Projects și Languages and Technologies | ||
| + | |||
| + | 1. **[10]** Aplicația trebuie să aibă două pagini: Home (CV-ul) și Contact | ||
| + | |||
| + | 2. **[30]** Informațiile secțiunilor din CV sunt populate de către server, și nu sunt scrise în template-ul Jinja. | ||
| + | Informațiile secțiunilor sunt stocate sub formă de dicționar. | ||
| + | De exemplu: | ||
| + | <code python> | ||
| + | work_exp = [ { position: "swe", company: "xyz", period: "Jun 2020 - Oct 2020" } ] | ||
| + | </code> | ||
| + | |||
| + | 3. **[10]** Folosiți icon-uri pentru Home și Contact | ||
| + | |||
| + | 4. **[20]** Folosiți componenta Bootstrap [[https://getbootstrap.com/docs/5.0/components/navbar/|Navbar]] pentru butoanele Home și Contact | ||
| + | |||
| + | 5. **[30]** Pagina de contact trebuie să conțină și un formular prin intermediul căruia un utilizator să vă poată contacta. | ||
| + | Formularul trebuie să conțină câmpurile: Nume, Adresă de e-mail și Mesaj. | ||
| + | Atunci când utilizatorul apasă butonul **Trimite** al formularului, serverul flask vă va //[simula că]// trimite un e-mail cu informațiile formularului prin scrierea unui fișier pe server (e.g., ''contact-mail.txt''). | ||